Skip to content

perf: Replace black with stdlib pprint for runtime formatting#235

Merged
gvanrossum merged 1 commit intomicrosoft:mainfrom
KRRT7:perf/optional-black
Apr 11, 2026
Merged

perf: Replace black with stdlib pprint for runtime formatting#235
gvanrossum merged 1 commit intomicrosoft:mainfrom
KRRT7:perf/optional-black

Conversation

@KRRT7
Copy link
Copy Markdown
Contributor

@KRRT7 KRRT7 commented Apr 10, 2026

Follows up on #229 (defer black import). Guido suggested making black fully optional at runtime.


black was only used at runtime in two cold formatting paths:

  • knowpro/answers.pycreate_context_prompt() formats a dict for LLM debug context
  • aitools/utils.pyformat_code() / pretty_print() formats Python literals for terminal output

Both format Python data structures, which is exactly what pprint.pformat does. Replaced black.format_str with pprint.pformat + ast.literal_eval — stdlib only, no conditional imports, no try/except.

Moved black from dependencies to dev dependency-group. It remains available for make format / make check but is no longer required by library consumers.

Changes

  • answers.py: pprint.pformat(dictify(context), width=200) replaces black.format_str(str(dictify(context)), ...)
  • utils.py: pretty_print uses pprint.pformat directly; format_code uses ast.literal_eval + pprint.pformat
  • pyproject.toml: black moved from dependencies to dev dependency-group
  • test_utils.py: updated existing test, added 3 new tests for pretty_print and format_code

Benchmark

Azure Standard_D2s_v5 — 2 vCPU, 8 GiB RAM, Python 3.13

Import Time (hyperfine, warmup 5, min-runs 30)

Benchmark Before After Speedup
import typeagent 713 ms ± 8 ms 713 ms ± 8 ms

Import time is unchanged because #229 already deferred the import black to first use. This PR removes the deferred import entirely and drops black + transitive deps (pathspec, platformdirs, tomli) from the runtime dependency tree.


Generated by codeflash optimization agent

black is only used at runtime in two cold formatting paths:
- create_context_prompt() in answers.py (LLM debug context)
- format_code()/pretty_print() in utils.py (developer terminal output)

Both format Python data structures, which is exactly what pprint does.
Replace black.format_str with pprint.pformat + ast.literal_eval,
eliminating the runtime dependency entirely.

Move black from dependencies to dev dependency-group — it remains
available for make format/check but is no longer required by library
consumers.
@gvanrossum gvanrossum merged commit 59be9a5 into microsoft:main Apr 11, 2026
16 checks passed
@gvanrossum
Copy link
Copy Markdown
Collaborator

gvanrossum commented Apr 11, 2026

@KRRT7 I like what this does, so I'm approving it. (EDIT: And merging.) Nevertheless I'd like to know how much you thought about this and how much was done by a coding agent (and which one). Could you be upfront about that please? Or are you an agent?

@KRRT7
Copy link
Copy Markdown
Contributor Author

KRRT7 commented Apr 11, 2026

I'm human :) We actually met briefly at PyCon last year — I mentioned I was building an optimization agent (codeflash) and you gave some helpful feedback. At PyBay when you demo'd typeagent it caught my attention because I thought I had an application for it, but got too busy to keep implementing it — anyways.

I've been building the agent for the past several months and I'm dogfooding it on open source projects to stress-test it on real codebases. For this PR specifically: I pointed the agent to your comment (GH MCP) about conditionally importing black, and it did the initial profiling and initially implemented a try/except import wrapper — catching ModuleNotFoundError and moving black to the optional dependency group. I reviewed that and didn't like it.

From the session transcript, I told it: "we want to come up with a way where 1) we don't do try except 2) move black to optional dependencies and 3) get the correct result" and "can we somehow get equivalent results with just stdlib or hook into another library somehow or similar". The agent found pprint.pformat as the stdlib replacement and implemented it.

So the split is roughly: agent did profiling + implementation, I reviewed everything and directed the design decisions.

@gvanrossum
Copy link
Copy Markdown
Collaborator

Cool. I wish you had mentioned that in the initial PR comment.

Worse, this introduced a bug that broker eval runs. I have a fix in #237.

Not sure if that's due to your optimization agent.

@KRRT7
Copy link
Copy Markdown
Contributor Author

KRRT7 commented Apr 13, 2026

Yes, it's on us, thanks for letting me know, I'll try to be more transparent about things in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants