Fix T201: replace print() with logger calls and remove suppression#193
Fix T201: replace print() with logger calls and remove suppression#193
print() with logger calls and remove suppression#193Conversation
Agent-Logs-Url: https://github.com/GitHubSecurityLab/seclab-taskflow-agent/sessions/6e40024a-509c-483c-8844-11b96abb0c87 Co-authored-by: kevinbackhouse <4358136+kevinbackhouse@users.noreply.github.com>
print() with logging/sys.stdout and remove suppression
|
@copilot fix the errors |
kevinbackhouse
left a comment
There was a problem hiding this comment.
@copilot fix the errors
…t/stderr.write() Agent-Logs-Url: https://github.com/GitHubSecurityLab/seclab-taskflow-agent/sessions/8acf69e6-94a8-40d4-a66c-2b90b143f143 Co-authored-by: kevinbackhouse <4358136+kevinbackhouse@users.noreply.github.com>
Fixed in 20557eb. The CI was failing because ruff also lints
Fixed in 20557eb. The CI was failing because ruff also lints Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
There was a problem hiding this comment.
Pull request overview
This PR removes the global Ruff suppression for T201 by replacing print() usage across the repo with either logging calls (for library/server code) or direct sys.stdout/sys.stderr writes (for CLI/scripts), keeping output behavior predictable while allowing the linter rule to be enforced.
Changes:
- Replaced
print()withsys.stdout.write()/sys.stderr.write()in scripts and release tooling. - Replaced
print()with module loggers in the CodeQL MCP server client and JSON-RPC transport code. - Removed
T201from the Ruff ignore list inpyproject.toml.
Show a summary per file
| File | Description |
|---|---|
src/seclab_taskflow_agent/render_utils.py |
Switch streamed output from print(..., flush=True) to sys.stdout.write() + flush() to preserve unbuffered behavior. |
src/seclab_taskflow_agent/mcp_servers/codeql/jsonrpyc/__init__.py |
Introduce logger and route JSON-RPC trace output through logger.debug() instead of print(). |
src/seclab_taskflow_agent/mcp_servers/codeql/client.py |
Add module logger and convert operational/diagnostic prints to debug/info/error logging. |
scripts/migrate_to_jinja2.py |
Convert user-facing console output from print() to sys.stdout/sys.stderr writes. |
release_tools/publish_docker.py |
Convert status/usage output from print() to sys.stdout/sys.stderr writes. |
release_tools/copy_files.py |
Convert progress/error output from print() to sys.stdout/sys.stderr writes. |
pyproject.toml |
Stop ignoring Ruff T201 now that print() calls have been removed from runtime code paths. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 7/7 changed files
- Comments generated: 2
| subprocess.run(["docker", "push", f"{image_name}:{tag}"], check=True) | ||
| print(f"Pushed {image_name}:{tag}") | ||
| sys.stdout.write(f"Pushed {image_name}:{tag}\n") | ||
| digest = get_image_digest(image_name, tag) |
There was a problem hiding this comment.
get_image_digest() can return None (when the docker buildx imagetools inspect output has no Digest: line). In that case this function will raise a TypeError when writing digest to /tmp/digest.txt. Handle the None case explicitly (e.g., raise a clear error before logging/writing, or default to an empty string).
| digest = get_image_digest(image_name, tag) | |
| digest = get_image_digest(image_name, tag) | |
| if digest is None: | |
| raise RuntimeError(f"Failed to determine image digest for {image_name}:{tag}") |
| if line: | ||
| decoded_line = line.decode("utf-8").strip() | ||
| match = re.search(r"^Content-Length:\s*([0-9]+)", decoded_line, re.IGNORECASE) | ||
| debug = False | ||
| if match: | ||
| if debug: | ||
| print(f"Incoming message header: {decoded_line}") | ||
| logger.debug(f"Incoming message header: {decoded_line}") | ||
| content_length = abs(int(match.group(1))) | ||
| _ = self.rpc.stdin.readline() | ||
| if debug: | ||
| print(f"Grabbing {content_length} bytes from stdin") | ||
| logger.debug(f"Grabbing {content_length} bytes from stdin") | ||
| msg = b"" | ||
| while len(msg) != content_length: | ||
| msg += self.rpc.stdin.read(content_length - len(msg)) | ||
| decoded_msg = msg.decode("utf-8").strip() | ||
| if debug: | ||
| print(f"Incoming jsonrpc message: {decoded_msg}") | ||
| logger.debug(f"Incoming jsonrpc message: {decoded_msg}") |
There was a problem hiding this comment.
These debug logs were previously gated behind a local debug = False flag, but are now unconditional. Given that the MCP servers configure root logging at DEBUG (e.g., mcp_servers/codeql/mcp_server.py), this will emit per-message header/body logs in a tight loop and can significantly increase log volume and overhead. Consider reintroducing an explicit toggle (env var / init flag) or reducing verbosity (e.g., only log message sizes/ids) to avoid runaway log files in normal operation.
|
@copilot : I don't see the benefit of replacing |
…lease_tools; fix None digest check Agent-Logs-Url: https://github.com/GitHubSecurityLab/seclab-taskflow-agent/sessions/c4f7447d-e20b-4794-b2d3-22a2387e63d4 Co-authored-by: kevinbackhouse <4358136+kevinbackhouse@users.noreply.github.com>
Done in a0a078d. Replaced all Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
…lines from log messages Agent-Logs-Url: https://github.com/GitHubSecurityLab/seclab-taskflow-agent/sessions/c4f7447d-e20b-4794-b2d3-22a2387e63d4 Co-authored-by: kevinbackhouse <4358136+kevinbackhouse@users.noreply.github.com>
print() with logging/sys.stdout and remove suppressionprint() with logger calls and remove suppression
T201 (
printfound) was globally suppressed inpyproject.toml. This removes the suppression by replacing allprint()calls withloggercalls throughout the codebase.Changes
render_utils.py: Replaceprint(data, end="", flush=True)withsys.stdout.write(data)+sys.stdout.flush()to preserve unbuffered terminal output semanticsmcp_servers/codeql/client.py: Addlogger = logging.getLogger(__name__)and convert all 19print()calls tologger.debug/info/error()based on severitymcp_servers/codeql/jsonrpyc/__init__.py: Add logger, replace activeprint()calls withlogger.debug(), and remove deaddebug = Falseguard blocks (replacing their unreachableprint()calls with unconditionallogger.debug())release_tools/copy_files.py: Addlogger = logging.getLogger(__name__)and convert allprint()calls tologger.info()/logger.error(); addlogging.basicConfig()in__main__release_tools/publish_docker.py: Add logger and convert allprint()calls tologger.info()/logger.error(); addlogging.basicConfig()in__main__; addNoneguard forget_image_digest()to raise a clearRuntimeErrorinstead of aTypeErrorscripts/migrate_to_jinja2.py: Add logger and convert allprint()calls tologger.info()/logger.error(); addlogging.basicConfig()inmain()pyproject.toml: Remove"T201"from the Ruffignorelist