• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #37483

pending completion
#37483

push

local

web-flow
Type-assert the value type in getindex(::AbstractDict, key) (#49115)

Closes https://github.com/JuliaCollections/OrderedCollections.jl/issues/101

2 of 2 new or added lines in 1 file covered. (100.0%)

72523 of 82770 relevant lines covered (87.62%)

34287845.75 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.01
/stdlib/Logging/src/ConsoleLogger.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
"""
4
    ConsoleLogger([stream,] min_level=Info; meta_formatter=default_metafmt,
5
                  show_limited=true, right_justify=0)
6

7
Logger with formatting optimized for readability in a text console, for example
8
interactive work with the Julia REPL.
9

10
Log levels less than `min_level` are filtered out.
11

12
Message formatting can be controlled by setting keyword arguments:
13

14
* `meta_formatter` is a function which takes the log event metadata
15
  `(level, _module, group, id, file, line)` and returns a color (as would be
16
  passed to printstyled), prefix and suffix for the log message.  The
17
  default is to prefix with the log level and a suffix containing the module,
18
  file and line location.
19
* `show_limited` limits the printing of large data structures to something
20
  which can fit on the screen by setting the `:limit` `IOContext` key during
21
  formatting.
22
* `right_justify` is the integer column which log metadata is right justified
23
  at. The default is zero (metadata goes on its own line).
24
"""
25
struct ConsoleLogger <: AbstractLogger
26
    stream::IO
472✔
27
    min_level::LogLevel
28
    meta_formatter
29
    show_limited::Bool
30
    right_justify::Int
31
    message_limits::Dict{Any,Int}
32
end
33
function ConsoleLogger(stream::IO, min_level=Info;
50✔
34
                       meta_formatter=default_metafmt, show_limited=true,
35
                       right_justify=0)
36
    ConsoleLogger(stream, min_level, meta_formatter,
24✔
37
                  show_limited, right_justify, Dict{Any,Int}())
38
end
39
function ConsoleLogger(min_level=Info;
896✔
40
                       meta_formatter=default_metafmt, show_limited=true,
41
                       right_justify=0)
42
    ConsoleLogger(closed_stream, min_level, meta_formatter,
448✔
43
                  show_limited, right_justify, Dict{Any,Int}())
44
end
45

46

47
shouldlog(logger::ConsoleLogger, level, _module, group, id) =
9✔
48
    get(logger.message_limits, id, 1) > 0
49

50
min_enabled_level(logger::ConsoleLogger) = logger.min_level
453✔
51

52
# Formatting of values in key value pairs
53
showvalue(io, msg) = show(io, "text/plain", msg)
5✔
54
function showvalue(io, e::Tuple{Exception,Any})
2✔
55
    ex,bt = e
2✔
56
    showerror(io, ex, bt; backtrace = bt!==nothing)
2✔
57
end
58
showvalue(io, ex::Exception) = showerror(io, ex)
1✔
59

60
function default_logcolor(level::LogLevel)
×
61
    level < Info  ? Base.debug_color() :
31✔
62
    level < Warn  ? Base.info_color()  :
63
    level < Error ? Base.warn_color()  :
64
                    Base.error_color()
65
end
66

67
function default_metafmt(level::LogLevel, _module, group, id, file, line)
16✔
68
    @nospecialize
×
69
    color = default_logcolor(level)
31✔
70
    prefix = string(level == Warn ? "Warning" : string(level), ':')
24✔
71
    suffix::String = ""
16✔
72
    Info <= level < Warn && return color, prefix, suffix
16✔
73
    _module !== nothing && (suffix *= string(_module)::String)
10✔
74
    if file !== nothing
10✔
75
        _module !== nothing && (suffix *= " ")
8✔
76
        suffix *= contractuser(file)::String
8✔
77
        if line !== nothing
8✔
78
            suffix *= ":$(isa(line, UnitRange) ? "$(first(line))-$(last(line))" : line)"
7✔
79
        end
80
    end
81
    !isempty(suffix) && (suffix = "@ " * suffix)
10✔
82
    return color, prefix, suffix
10✔
83
end
84

85
# Length of a string as it will appear in the terminal (after ANSI color codes
86
# are removed)
87
function termlength(str)
25✔
88
    N = 0
×
89
    in_esc = false
×
90
    for c in str
49✔
91
        if in_esc
348✔
92
            if c == 'm'
×
93
                in_esc = false
×
94
            end
95
        else
96
            if c == '\e'
348✔
97
                in_esc = true
×
98
            else
99
                N += 1
348✔
100
            end
101
        end
102
    end
672✔
103
    return N
25✔
104
end
105

106
function handle_message(logger::ConsoleLogger, level::LogLevel, message, _module, group, id,
53✔
107
                        filepath, line; kwargs...)
108
    @nospecialize
×
109
    hasmaxlog = haskey(kwargs, :maxlog) ? 1 : 0
26✔
110
    maxlog = get(kwargs, :maxlog, nothing)
48✔
111
    if maxlog isa Core.BuiltinInts
26✔
112
        remaining = get!(logger.message_limits, id, Int(maxlog)::Int)
8✔
113
        logger.message_limits[id] = remaining - 1
4✔
114
        remaining > 0 || return
5✔
115
    end
116

117
    # Generate a text representation of the message and all key value pairs,
118
    # split into lines.
119
    msglines = [(indent=0, msg=l) for l in split(chomp(convert(String, string(message))::String), '\n')]
25✔
120
    stream::IO = logger.stream
25✔
121
    if !(isopen(stream)::Bool)
25✔
122
        stream = stderr
2✔
123
    end
124
    dsize = displaysize(stream)::Tuple{Int,Int}
25✔
125
    nkwargs = length(kwargs)::Int
25✔
126
    if nkwargs > hasmaxlog
25✔
127
        valbuf = IOBuffer()
5✔
128
        rows_per_value = max(1, dsize[1] รท (nkwargs + 1 - hasmaxlog))
5✔
129
        valio = IOContext(IOContext(valbuf, stream),
5✔
130
                          :displaysize => (rows_per_value, dsize[2] - 5),
131
                          :limit => logger.show_limited)
132
        for (key, val) in kwargs
10✔
133
            key === :maxlog && continue
7✔
134
            showvalue(valio, val)
7✔
135
            vallines = split(String(take!(valbuf)), '\n')
7✔
136
            if length(vallines) == 1
7✔
137
                push!(msglines, (indent=2, msg=SubString("$key = $(vallines[1])")))
3✔
138
            else
139
                push!(msglines, (indent=2, msg=SubString("$key =")))
4✔
140
                append!(msglines, ((indent=3, msg=line) for line in vallines))
4✔
141
            end
142
        end
9✔
143
    end
144

145
    # Format lines as text with appropriate indentation and with a box
146
    # decoration on the left.
147
    color, prefix, suffix = logger.meta_formatter(level, _module, group, id, filepath, line)::Tuple{Union{Symbol,Int},String,String}
25✔
148
    minsuffixpad = 2
×
149
    buf = IOBuffer()
25✔
150
    iob = IOContext(buf, stream)
25✔
151
    nonpadwidth = 2 + (isempty(prefix) || length(msglines) > 1 ? 0 : length(prefix)+1) +
44✔
152
                  msglines[end].indent + termlength(msglines[end].msg) +
153
                  (isempty(suffix) ? 0 : length(suffix)+minsuffixpad)
154
    justify_width = min(logger.right_justify, dsize[2])
25✔
155
    if nonpadwidth > justify_width && !isempty(suffix)
25✔
156
        push!(msglines, (indent=0, msg=SubString("")))
15✔
157
        minsuffixpad = 0
×
158
        nonpadwidth = 2 + length(suffix)
15✔
159
    end
160
    for (i, (indent, msg)) in enumerate(msglines)
50✔
161
        boxstr = length(msglines) == 1 ? "[ " :
222✔
162
                 i == 1                ? "โ”Œ " :
163
                 i < length(msglines)  ? "โ”‚ " :
164
                                         "โ”” "
165
        printstyled(iob, boxstr, bold=true, color=color)
115✔
166
        if i == 1 && !isempty(prefix)
115✔
167
            printstyled(iob, prefix, " ", bold=true, color=color)
24✔
168
        end
169
        print(iob, " "^indent, msg)
115✔
170
        if i == length(msglines) && !isempty(suffix)
115✔
171
            npad = max(0, justify_width - nonpadwidth) + minsuffixpad
19✔
172
            print(iob, " "^npad)
19✔
173
            printstyled(iob, suffix, color=:light_black)
19✔
174
        end
175
        println(iob)
115✔
176
    end
205✔
177

178
    write(stream, take!(buf))
25✔
179
    nothing
25✔
180
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc