Rename metadata_parser module to chip.testing (#35615)
* Rename metadata_parser module to chip.testing
* MCORE_FS_1_4: Use Subprocess from chip.testing
* MCORE_FS_1_3: Use Subprocess from chip.testing
* Cleanup unused arguments
* Restyled by isort
* Fix test case to work on CI
diff --git a/BUILD.gn b/BUILD.gn
index 9a0654a..e05f143 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -81,7 +81,7 @@
"//examples/common/pigweed/rpc_console/py:chip_rpc",
"//integrations/mobly:chip_mobly",
"//scripts/py_matter_yamltests:matter_yamltests",
- "//src/python_testing/matter_testing_infrastructure:metadata_parser",
+ "//src/python_testing/matter_testing_infrastructure:chip-testing",
]
pw_python_venv("matter_build_venv") {
@@ -122,7 +122,7 @@
deps = [
"${chip_root}/scripts:matter_yamltests_distribution.wheel",
"${chip_root}/src/controller/python:chip-repl",
- "${chip_root}/src/python_testing/matter_testing_infrastructure:metadata_parser.wheel",
+ "${chip_root}/src/python_testing/matter_testing_infrastructure:chip-testing.wheel",
]
}
}
@@ -249,7 +249,7 @@
"//scripts/py_matter_idl:matter_idl.tests",
"//scripts/py_matter_yamltests:matter_yamltests.tests",
"//src:tests_run",
- "//src/python_testing/matter_testing_infrastructure:metadata_parser.tests",
+ "//src/python_testing/matter_testing_infrastructure:chip-testing.tests",
]
if (current_os == "linux" || current_os == "mac") {
diff --git a/examples/fabric-admin/scripts/fabric-sync-app.py b/examples/fabric-admin/scripts/fabric-sync-app.py
index 78e8f84..3967f97 100755
--- a/examples/fabric-admin/scripts/fabric-sync-app.py
+++ b/examples/fabric-admin/scripts/fabric-sync-app.py
@@ -79,12 +79,11 @@
class Subprocess:
- def __init__(self, tag: str, program: str, *args, stdout_cb=None):
+ def __init__(self, tag: str, program: str, *args):
self.event = asyncio.Event()
self.tag = tag.encode()
self.program = program
self.args = args
- self.stdout_cb = stdout_cb
self.expected_output = None
def _check_output(self, line: bytes):
@@ -122,8 +121,7 @@
self.p.terminate()
-async def run_admin(program, stdout_cb=None, storage_dir=None,
- rpc_admin_port=None, rpc_bridge_port=None,
+async def run_admin(program, storage_dir=None, rpc_admin_port=None, rpc_bridge_port=None,
paa_trust_store_path=None, commissioner_name=None,
commissioner_node_id=None, commissioner_vendor_id=None):
args = []
@@ -141,8 +139,7 @@
args.extend(["--commissioner-nodeid", str(commissioner_node_id)])
if commissioner_vendor_id is not None:
args.extend(["--commissioner-vendor-id", str(commissioner_vendor_id)])
- p = Subprocess("[FS-ADMIN]", program, "interactive", "start", *args,
- stdout_cb=stdout_cb)
+ p = Subprocess("[FS-ADMIN]", program, "interactive", "start", *args)
await p.run()
return p
diff --git a/scripts/build_python.sh b/scripts/build_python.sh
index eaf1ad9..da3fe0c 100755
--- a/scripts/build_python.sh
+++ b/scripts/build_python.sh
@@ -198,7 +198,7 @@
WHEEL=("$OUTPUT_ROOT"/controller/python/chip*.whl)
# Add the matter_testing_infrastructure wheel
-WHEEL+=("$OUTPUT_ROOT"/python/obj/src/python_testing/matter_testing_infrastructure/metadata_parser._build_wheel/metadata_parser-*.whl)
+WHEEL+=("$OUTPUT_ROOT"/python/obj/src/python_testing/matter_testing_infrastructure/chip-testing._build_wheel/chip_testing-*.whl)
if [ -n "$extra_packages" ]; then
WHEEL+=("$extra_packages")
diff --git a/scripts/tests/run_python_test.py b/scripts/tests/run_python_test.py
index eb8f063..6474819 100755
--- a/scripts/tests/run_python_test.py
+++ b/scripts/tests/run_python_test.py
@@ -31,8 +31,8 @@
import click
import coloredlogs
+from chip.testing.metadata import Metadata, MetadataReader
from colorama import Fore, Style
-from metadata_parser.metadata import Metadata, MetadataReader
DEFAULT_CHIP_ROOT = os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', '..'))
diff --git a/src/python_testing/TC_MCORE_FS_1_3.py b/src/python_testing/TC_MCORE_FS_1_3.py
index 2a21c97..1270b56 100644
--- a/src/python_testing/TC_MCORE_FS_1_3.py
+++ b/src/python_testing/TC_MCORE_FS_1_3.py
@@ -36,67 +36,33 @@
import logging
import os
import random
-import subprocess
-import sys
import tempfile
-import threading
import chip.clusters as Clusters
from chip import ChipDeviceCtrl
from chip.interaction_model import Status
+from chip.testing.tasks import Subprocess
from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main, type_matches
from mobly import asserts
-# TODO: Make this class more generic. Issue #35348
-class Subprocess(threading.Thread):
-
- def __init__(self, args: list = [], tag="", **kw):
- super().__init__(**kw)
- self.tag = f"[{tag}] " if tag else ""
- self.args = args
-
- def forward_f(self, f_in, f_out):
- while True:
- line = f_in.readline()
- if not line:
- break
- f_out.write(f"{self.tag}{line}")
- f_out.flush()
-
- def run(self):
- logging.info("RUN: %s", " ".join(self.args))
- self.p = subprocess.Popen(self.args, errors="ignore", stdin=subprocess.PIPE,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- # Forward stdout and stderr with a tag attached.
- t1 = threading.Thread(target=self.forward_f, args=[self.p.stdout, sys.stdout])
- t1.start()
- t2 = threading.Thread(target=self.forward_f, args=[self.p.stderr, sys.stderr])
- t2.start()
- # Wait for the process to finish.
- self.p.wait()
- t1.join()
- t2.join()
-
- def stop(self):
- self.p.terminate()
- self.join()
-
-
class AppServer:
def __init__(self, app, storage_dir, port=None, discriminator=None, passcode=None):
-
- args = [app]
- args.extend(["--KVS", tempfile.mkstemp(dir=storage_dir, prefix="kvs-app-")[1]])
+ args = [
+ "--KVS", tempfile.mkstemp(dir=storage_dir, prefix="kvs-app-")[1],
+ ]
args.extend(['--secured-device-port', str(port)])
args.extend(["--discriminator", str(discriminator)])
args.extend(["--passcode", str(passcode)])
- self.app = Subprocess(args, tag="SERVER")
- self.app.start()
+ self.app = Subprocess(app, *args, prefix="[SERVER]")
- def stop(self):
- self.app.stop()
+ def start(self):
+ # Start process and block until it prints the expected output.
+ self.app.start(expected_output="Server initialization complete")
+
+ def terminate(self):
+ self.app.terminate()
class TC_MCORE_FS_1_3(MatterBaseTest):
@@ -134,10 +100,11 @@
port=self.th_server_port,
discriminator=self.th_server_discriminator,
passcode=self.th_server_passcode)
+ self.th_server.start()
def teardown_class(self):
if self.th_server is not None:
- self.th_server.stop()
+ self.th_server.terminate()
if self.storage is not None:
self.storage.cleanup()
super().teardown_class()
diff --git a/src/python_testing/TC_MCORE_FS_1_4.py b/src/python_testing/TC_MCORE_FS_1_4.py
index c776bd2..7b101bb 100644
--- a/src/python_testing/TC_MCORE_FS_1_4.py
+++ b/src/python_testing/TC_MCORE_FS_1_4.py
@@ -36,86 +36,32 @@
import logging
import os
import random
-import subprocess
-import sys
import tempfile
-import threading
import chip.clusters as Clusters
from chip import ChipDeviceCtrl
from chip.interaction_model import Status
+from chip.testing.tasks import Subprocess
from matter_testing_support import MatterBaseTest, TestStep, async_test_body, default_matter_test_main, type_matches
from mobly import asserts
-# TODO: Make this class more generic. Issue #35348
-
-
-class Subprocess(threading.Thread):
-
- def __init__(self, args: list = [], stdout_cb=None, tag="", **kw):
- super().__init__(**kw)
- self.tag = f"[{tag}] " if tag else ""
- self.stdout_cb = stdout_cb
- self.args = args
-
- def forward_f(self, f_in, f_out):
- while True:
- line = f_in.readline()
- if not line:
- break
- f_out.write(f"{self.tag}{line}")
- f_out.flush()
- if self.stdout_cb is not None:
- self.stdout_cb(line)
-
- def run(self):
- logging.info("RUN: %s", " ".join(self.args))
- self.p = subprocess.Popen(self.args, errors="ignore", stdin=subprocess.PIPE,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- # Forward stdout and stderr with a tag attached.
- forwarding_stdout_thread = threading.Thread(target=self.forward_f, args=[self.p.stdout, sys.stdout])
- forwarding_stdout_thread.start()
- forwarding_stderr_thread = threading.Thread(target=self.forward_f, args=[self.p.stderr, sys.stderr])
- forwarding_stderr_thread.start()
- # Wait for the process to finish.
- self.p.wait()
- forwarding_stdout_thread.join()
- forwarding_stderr_thread.join()
-
- def stop(self):
- self.p.terminate()
- self.join()
-
class FabricSyncApp:
- def _process_admin_output(self, line):
- if self.wait_for_text_text is not None and self.wait_for_text_text in line:
- self.wait_for_text_event.set()
-
- def wait_for_text(self, timeout=30):
- if not self.wait_for_text_event.wait(timeout=timeout):
- raise Exception(f"Timeout waiting for text: {self.wait_for_text_text}")
- self.wait_for_text_event.clear()
- self.wait_for_text_text = None
-
def __init__(self, fabric_sync_app_path, fabric_admin_app_path, fabric_bridge_app_path,
storage_dir, fabric_name=None, node_id=None, vendor_id=None,
paa_trust_store_path=None, bridge_port=None, bridge_discriminator=None,
bridge_passcode=None):
-
- self.wait_for_text_event = threading.Event()
- self.wait_for_text_text = None
-
- args = [fabric_sync_app_path]
- args.append(f"--app-admin={fabric_admin_app_path}")
- args.append(f"--app-bridge={fabric_bridge_app_path}")
- # Override default ports, so it will be possible to run
- # our TH_FSA alongside the DUT_FSA during CI testing.
- args.append("--app-admin-rpc-port=44000")
- args.append("--app-bridge-rpc-port=44001")
- # Keep the storage directory in a temporary location.
- args.append(f"--storage-dir={storage_dir}")
+ args = [
+ f"--app-admin={fabric_admin_app_path}",
+ f"--app-bridge={fabric_bridge_app_path}",
+ # Override default ports, so it will be possible to run
+ # our TH_FSA alongside the DUT_FSA during CI testing.
+ "--app-admin-rpc-port=44000",
+ "--app-bridge-rpc-port=44001",
+ # Keep the storage directory in a temporary location.
+ f"--storage-dir={storage_dir}",
+ ]
if paa_trust_store_path is not None:
args.append(f"--paa-trust-store-path={paa_trust_store_path}")
if fabric_name is not None:
@@ -127,55 +73,38 @@
args.append(f"--discriminator={bridge_discriminator}")
args.append(f"--passcode={bridge_passcode}")
- self.fabric_sync_app = Subprocess(args, stdout_cb=self._process_admin_output)
- self.wait_for_text_text = "Successfully opened pairing window on the device"
- self.fabric_sync_app.start()
+ self.fabric_sync_app = Subprocess(fabric_sync_app_path, *args)
- # Wait for the fabric-sync-app to be ready.
- self.wait_for_text()
+ def start(self):
+ # Start process and block until it prints the expected output.
+ self.fabric_sync_app.start(expected_output="Successfully opened pairing window on the device")
+
+ def terminate(self):
+ self.fabric_sync_app.terminate()
def commission_on_network(self, node_id, setup_pin_code=None, filter_type=None, filter=None):
- self.wait_for_text_text = f"Commissioning complete for node ID {node_id:#018x}: success"
- # Send the commissioning command to the admin.
- self.fabric_sync_app.p.stdin.write(f"pairing onnetwork {node_id} {setup_pin_code}\n")
- self.fabric_sync_app.p.stdin.flush()
- # Wait for success message.
- self.wait_for_text()
-
- def stop(self):
- self.fabric_sync_app.stop()
+ self.fabric_sync_app.send(
+ f"pairing onnetwork {node_id} {setup_pin_code}",
+ expected_output=f"Commissioning complete for node ID {node_id:#018x}: success")
class AppServer:
- def _process_admin_output(self, line):
- if self.wait_for_text_text is not None and self.wait_for_text_text in line:
- self.wait_for_text_event.set()
-
- def wait_for_text(self, timeout=30):
- if not self.wait_for_text_event.wait(timeout=timeout):
- raise Exception(f"Timeout waiting for text: {self.wait_for_text_text}")
- self.wait_for_text_event.clear()
- self.wait_for_text_text = None
-
def __init__(self, app, storage_dir, port=None, discriminator=None, passcode=None):
- self.wait_for_text_event = threading.Event()
- self.wait_for_text_text = None
-
- args = [app]
- args.extend(["--KVS", tempfile.mkstemp(dir=storage_dir, prefix="kvs-app-")[1]])
+ args = [
+ "--KVS", tempfile.mkstemp(dir=storage_dir, prefix="kvs-app-")[1],
+ ]
args.extend(['--secured-device-port', str(port)])
args.extend(["--discriminator", str(discriminator)])
args.extend(["--passcode", str(passcode)])
- self.app = Subprocess(args, stdout_cb=self._process_admin_output, tag="SERVER")
- self.wait_for_text_text = "Server initialization complete"
- self.app.start()
+ self.app = Subprocess(app, *args, prefix="[SERVER]")
- # Wait for the server-app to be ready.
- self.wait_for_text()
+ def start(self):
+ # Start process and block until it prints the expected output.
+ self.app.start(expected_output="Server initialization complete")
- def stop(self):
- self.app.stop()
+ def terminate(self):
+ self.app.terminate()
class TC_MCORE_FS_1_4(MatterBaseTest):
@@ -237,6 +166,7 @@
bridge_discriminator=self.th_fsa_bridge_discriminator,
bridge_passcode=self.th_fsa_bridge_passcode,
vendor_id=0xFFF1)
+ self.th_fsa_controller.start()
# Get the named pipe path for the DUT_FSA app input from the user params.
dut_fsa_stdin_pipe = self.user_params.get("dut_fsa_stdin_pipe", None)
@@ -254,12 +184,13 @@
port=self.th_server_port,
discriminator=self.th_server_discriminator,
passcode=self.th_server_passcode)
+ self.th_server.start()
def teardown_class(self):
if self.th_fsa_controller is not None:
- self.th_fsa_controller.stop()
+ self.th_fsa_controller.terminate()
if self.th_server is not None:
- self.th_server.stop()
+ self.th_server.terminate()
if self.storage is not None:
self.storage.cleanup()
super().teardown_class()
diff --git a/src/python_testing/matter_testing_infrastructure/BUILD.gn b/src/python_testing/matter_testing_infrastructure/BUILD.gn
index f972040..c8d54fb 100644
--- a/src/python_testing/matter_testing_infrastructure/BUILD.gn
+++ b/src/python_testing/matter_testing_infrastructure/BUILD.gn
@@ -18,7 +18,8 @@
import("//build_overrides/pigweed.gni")
import("$dir_pw_build/python.gni")
-pw_python_package("metadata_parser") {
+# Python package for CHIP testing support.
+pw_python_package("chip-testing") {
setup = [
"setup.py",
"setup.cfg",
@@ -28,9 +29,13 @@
inputs = [ "env_test.yaml" ]
sources = [
- "metadata_parser/__init__.py",
- "metadata_parser/metadata.py",
+ "chip/testing/__init__.py",
+ "chip/testing/metadata.py",
+ "chip/testing/tasks.py",
]
- tests = [ "metadata_parser/test_metadata.py" ]
+ tests = [
+ "chip/testing/test_metadata.py",
+ "chip/testing/test_tasks.py",
+ ]
}
diff --git a/src/python_testing/matter_testing_infrastructure/metadata_parser/__init__.py b/src/python_testing/matter_testing_infrastructure/chip/testing/__init__.py
similarity index 100%
rename from src/python_testing/matter_testing_infrastructure/metadata_parser/__init__.py
rename to src/python_testing/matter_testing_infrastructure/chip/testing/__init__.py
diff --git a/src/python_testing/matter_testing_infrastructure/metadata_parser/metadata.py b/src/python_testing/matter_testing_infrastructure/chip/testing/metadata.py
similarity index 99%
rename from src/python_testing/matter_testing_infrastructure/metadata_parser/metadata.py
rename to src/python_testing/matter_testing_infrastructure/chip/testing/metadata.py
index f16d3e9..aa829c4 100644
--- a/src/python_testing/matter_testing_infrastructure/metadata_parser/metadata.py
+++ b/src/python_testing/matter_testing_infrastructure/chip/testing/metadata.py
@@ -1,4 +1,3 @@
-#!/usr/bin/python3
# Copyright (c) 2024 Project CHIP Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/tasks.py b/src/python_testing/matter_testing_infrastructure/chip/testing/tasks.py
new file mode 100644
index 0000000..873cec5
--- /dev/null
+++ b/src/python_testing/matter_testing_infrastructure/chip/testing/tasks.py
@@ -0,0 +1,124 @@
+# Copyright (c) 2024 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging
+import subprocess
+import sys
+import threading
+import typing
+
+
+def forward_f(prefix: bytes,
+ f_in: typing.BinaryIO,
+ f_out: typing.BinaryIO,
+ cb: typing.Optional[typing.Callable[[bytes, bool], None]] = None,
+ is_stderr: bool = False):
+ """Forward f_in to f_out with a prefix attached.
+
+ This function can optionally feed received lines to a callback function.
+ """
+ while True:
+ line = f_in.readline()
+ if not line:
+ break
+ if cb is not None:
+ cb(line, is_stderr)
+ f_out.buffer.write(prefix)
+ f_out.buffer.write(line)
+ f_out.flush()
+
+
+class Subprocess(threading.Thread):
+ """Run a subprocess and optionally prefix its output."""
+
+ def __init__(self, program: str, *args: typing.List[str], prefix: str = "",
+ output_cb: typing.Optional[typing.Callable[[bytes, bool], None]] = None):
+ """Initialize the subprocess.
+
+ Args:
+ program: The program to run.
+ args: The arguments to the program.
+ prefix: A prefix to attach to the output.
+ output_cb: A callback function to process the output. It should take two
+ arguments: the output line bytes and the boolean indicating if the
+ output comes from stderr.
+ """
+ super().__init__()
+ self.event = threading.Event()
+ self.prefix = prefix.encode()
+ self.program = program
+ self.args = args
+ self.output_cb = output_cb
+ self.expected_output = None
+
+ def _check_output(self, line: bytes, is_stderr: bool):
+ if self.output_cb is not None:
+ self.output_cb(line, is_stderr)
+ if self.expected_output is not None and self.expected_output in line:
+ self.event.set()
+
+ def run(self):
+ """Thread entry point."""
+
+ logging.info("RUN: %s %s", self.program, " ".join(self.args))
+ self.p = subprocess.Popen([self.program] + list(self.args),
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+
+ # Forward stdout and stderr with a tag attached.
+ forwarding_stdout_thread = threading.Thread(
+ target=forward_f,
+ args=(self.prefix, self.p.stdout, sys.stdout, self._check_output))
+ forwarding_stdout_thread.start()
+ forwarding_stderr_thread = threading.Thread(
+ target=forward_f,
+ args=(self.prefix, self.p.stderr, sys.stderr, self._check_output, True))
+ forwarding_stderr_thread.start()
+
+ # Wait for the process to finish.
+ self.p.wait()
+
+ forwarding_stdout_thread.join()
+ forwarding_stderr_thread.join()
+
+ def start(self, expected_output: str = None, timeout: float = None):
+ """Start a subprocess and optionally wait for a specific output."""
+ if expected_output is not None:
+ self.expected_output = expected_output.encode()
+ self.event.clear()
+ super().start()
+ if expected_output is not None:
+ if self.event.wait(timeout) is False:
+ raise TimeoutError("Expected output not found")
+ self.expected_output = None
+
+ def send(self, message: str, end: str = "\n",
+ expected_output: str = None, timeout: float = None):
+ """Send a message to a process and optionally wait for a response."""
+
+ if expected_output is not None:
+ self.expected_output = expected_output.encode()
+ self.event.clear()
+
+ self.p.stdin.write((message + end).encode())
+ self.p.stdin.flush()
+
+ if expected_output is not None:
+ if self.event.wait(timeout) is False:
+ raise TimeoutError("Expected output not found")
+ self.expected_output = None
+
+ def terminate(self):
+ self.p.terminate()
diff --git a/src/python_testing/matter_testing_infrastructure/metadata_parser/test_metadata.py b/src/python_testing/matter_testing_infrastructure/chip/testing/test_metadata.py
similarity index 100%
rename from src/python_testing/matter_testing_infrastructure/metadata_parser/test_metadata.py
rename to src/python_testing/matter_testing_infrastructure/chip/testing/test_metadata.py
diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/test_tasks.py b/src/python_testing/matter_testing_infrastructure/chip/testing/test_tasks.py
new file mode 100644
index 0000000..5e91a89
--- /dev/null
+++ b/src/python_testing/matter_testing_infrastructure/chip/testing/test_tasks.py
@@ -0,0 +1,35 @@
+# Copyright (c) 2024 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+
+from tasks import Subprocess
+
+
+class TestSubprocess(unittest.TestCase):
+
+ def test_expected_output(self):
+ p = Subprocess("python3", "-c", "print('Hello, World!')")
+ p.start(expected_output="Hello, World!", timeout=1)
+ p.terminate()
+
+ def test_expected_output_timeout(self):
+ p = Subprocess("python3", "--version")
+ with self.assertRaises(TimeoutError):
+ p.start(expected_output="Python 1.0.0", timeout=1)
+ p.terminate()
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/src/python_testing/matter_testing_infrastructure/setup.cfg b/src/python_testing/matter_testing_infrastructure/setup.cfg
index d1cbadf..862236a 100644
--- a/src/python_testing/matter_testing_infrastructure/setup.cfg
+++ b/src/python_testing/matter_testing_infrastructure/setup.cfg
@@ -13,7 +13,9 @@
# limitations under the License.
[metadata]
-name = metadata_parser
-version = 0.0.1
+name = chip-testing
+version = 1.0.0
author = Project CHIP Authors
-description = Scripts to get metadata (runner arguments) associated with the python_testing scripts
\ No newline at end of file
+license-expression = Apache-2.0
+description = Various helpers associated with the python_testing scripts
+url = https://github.com/project-chip/connectedhomeip
diff --git a/src/python_testing/matter_testing_infrastructure/setup.py b/src/python_testing/matter_testing_infrastructure/setup.py
index 8a92fbd..ab0a7f3 100644
--- a/src/python_testing/matter_testing_infrastructure/setup.py
+++ b/src/python_testing/matter_testing_infrastructure/setup.py
@@ -12,9 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-
-"""The metadata_parser package."""
-
import setuptools # type: ignore
setuptools.setup() # Package definition in setup.cfg