Skip to content

Commit e358a52

Browse files
authored
better compact printing of Py (#684)
* better compact printing of Py * add tests for compact printing * update release notes --------- Co-authored-by: Christopher Doris <github.com/cjdoris>
1 parent 5f8f8f7 commit e358a52

File tree

3 files changed

+37
-4
lines changed

3 files changed

+37
-4
lines changed

docs/src/releasenotes.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Release Notes
22

3+
## Unreleased
4+
* Showing `Py` now respects the `compact` option - output is limited to a single line of
5+
at most the display width.
6+
* Bug fixes.
7+
38
## 0.9.28 (2025-09-17)
49
* Added `NumpyDates`: NumPy-compatible DateTime64/TimeDelta64 types and units.
510
* Added `pyconvert` rules for NumpyDates types.

src/Core/Py.jl

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,16 +168,23 @@ function Base.show(io::IO, ::MIME"text/plain", o::Py)
168168
end
169169
hasprefix = (get(io, :typeinfo, Any) != Py)::Bool
170170
compact = get(io, :compact, false)::Bool
171+
limit = get(io, :limit, true)::Bool
172+
if compact
173+
# compact should output a single line, which we force by replacing newline
174+
# characters with spaces
175+
str = replace(str, "\n" => " ")
176+
end
171177
multiline = '\n' in str
172-
prefix =
173-
hasprefix ?
174-
compact ? "Py:$(multiline ? '\n' : ' ')" : "Python:$(multiline ? '\n' : ' ')" : ""
178+
prefix = !hasprefix ? "" : compact ? "Py: " : multiline ? "Python:\n" : "Python: "
175179
print(io, prefix)
176180
h, w = displaysize(io)
177-
if get(io, :limit, true)
181+
if limit
182+
# limit: fit the printed text into the display size
178183
h, w = displaysize(io)
179184
h = max(h - 3, 5) # use 3 fewer lines to allow for the prompt, but always allow at least 5 lines
180185
if multiline
186+
# multiline: we truncate each line to the width of the screen, and skip
187+
# middle lines if there are too many for the height
181188
h -= 1 # for the prefix
182189
lines = split(str, '\n')
183190
function printlines(io, lines, w)
@@ -218,7 +225,25 @@ function Base.show(io::IO, ::MIME"text/plain", o::Py)
218225
println(io)
219226
printlines(io, lines[end-h1+1:end], w)
220227
end
228+
elseif compact
229+
# compact: we print up to one screen width, skipping characters in the
230+
# middle if the string is too long for the width
231+
maxlen = w - length(prefix)
232+
if length(str) maxlen
233+
print(io, str)
234+
else
235+
gap = " ... "
236+
gaplen = length(gap)
237+
w0 = cld(maxlen - gaplen, 2)
238+
i0 = nextind(str, 1, w0 - 1)
239+
i1 = prevind(str, ncodeunits(str), maxlen - gaplen - w0 - 1)
240+
print(io, str[begin:i0])
241+
printstyled(io, gap, color = :light_black)
242+
print(io, str[i1:end])
243+
end
221244
else
245+
# single-line: we print up to one screenfull, skipping characters in the
246+
# middle if the string is too long. We skip a whole line of characters.
222247
maxlen = h * w - length(prefix)
223248
if length(str) maxlen
224249
print(io, str)

test/Core.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,9 @@ end
805805
@test sprint(show, MIME("text/plain"), Py(12)) == "Python: 12"
806806
# https://github.com/JuliaPy/PythonCall.jl/issues/522
807807
@test sprint(show, MIME("text/plain"), PythonCall.pynew()) == "Python: NULL"
808+
# test compact printing
809+
@test sprint(show, MIME("text/plain"), Py(String('A':'Z')), context=(:compact=>true, :displaysize=>(50, 20))) == "Py: 'ABCDE ... WXYZ'"
810+
@test sprint(show, MIME("text/plain"), Py(String('A':'Z')), context=(:compact=>true, :limit=>false, :displaysize=>(50, 20))) == "Py: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"
808811
@test_throws MethodError sprint(show, MIME("text/html"), PythonCall.pynew())
809812
end
810813
end

0 commit comments

Comments
 (0)