@@ -2994,6 +2994,193 @@ end
29942994
29952995@deprecate merge! (repo:: LibGit2.GitRepo , args... ; kwargs... ) LibGit2. merge! (repo, args... ; kwargs... )
29962996
2997+ # 24490 - warnings and messages
2998+ const log_info_to = Dict {Tuple{Union{Module,Void},Union{Symbol,Void}},IO} ()
2999+ const log_warn_to = Dict {Tuple{Union{Module,Void},Union{Symbol,Void}},IO} ()
3000+ const log_error_to = Dict {Tuple{Union{Module,Void},Union{Symbol,Void}},IO} ()
3001+
3002+ function _redirect (io:: IO , log_to:: Dict , sf:: StackTraces.StackFrame )
3003+ (sf. linfo isa Core. MethodInstance) || return io
3004+ mod = sf. linfo. def
3005+ isa (mod, Method) && (mod = mod. module)
3006+ fun = sf. func
3007+ if haskey (log_to, (mod,fun))
3008+ return log_to[(mod,fun)]
3009+ elseif haskey (log_to, (mod,nothing ))
3010+ return log_to[(mod,nothing )]
3011+ elseif haskey (log_to, (nothing ,nothing ))
3012+ return log_to[(nothing ,nothing )]
3013+ else
3014+ return io
3015+ end
3016+ end
3017+
3018+ function _redirect (io:: IO , log_to:: Dict , fun:: Symbol )
3019+ clos = string (" #" ,fun," #" )
3020+ kw = string (" kw##" ,fun)
3021+ local sf
3022+ break_next_frame = false
3023+ for trace in backtrace ()
3024+ stack:: Vector{StackFrame} = StackTraces. lookup (trace)
3025+ filter! (frame -> ! frame. from_c, stack)
3026+ for frame in stack
3027+ (frame. linfo isa Core. MethodInstance) || continue
3028+ sf = frame
3029+ break_next_frame && (@goto skip)
3030+ mod = frame. linfo. def
3031+ isa (mod, Method) && (mod = mod. module)
3032+ mod === Base || continue
3033+ sff = string (frame. func)
3034+ if frame. func == fun || startswith (sff, clos) || startswith (sff, kw)
3035+ break_next_frame = true
3036+ end
3037+ end
3038+ end
3039+ @label skip
3040+ _redirect (io, log_to, sf)
3041+ end
3042+
3043+ @inline function redirect (io:: IO , log_to:: Dict , arg:: Union{Symbol,StackTraces.StackFrame} )
3044+ if isempty (log_to)
3045+ return io
3046+ else
3047+ if length (log_to)== 1 && haskey (log_to,(nothing ,nothing ))
3048+ return log_to[(nothing ,nothing )]
3049+ else
3050+ return _redirect (io, log_to, arg)
3051+ end
3052+ end
3053+ end
3054+
3055+ """
3056+ logging(io [, m [, f]][; kind=:all])
3057+ logging([; kind=:all])
3058+
3059+ Stream output of informational, warning, and/or error messages to `io`,
3060+ overriding what was otherwise specified. Optionally, divert stream only for
3061+ module `m`, or specifically function `f` within `m`. `kind` can be `:all` (the
3062+ default), `:info`, `:warn`, or `:error`. See `Base.log_{info,warn,error}_to`
3063+ for the current set of redirections. Call `logging` with no arguments (or just
3064+ the `kind`) to reset everything.
3065+ """
3066+ function logging (io:: IO , m:: Union{Module,Void} = nothing , f:: Union{Symbol,Void} = nothing ;
3067+ kind:: Symbol = :all )
3068+ depwarn (""" `logging()` is deprecated, use `with_logger` instead to capture
3069+ messages from `Base`""" , :logging )
3070+ (kind== :all || kind== :info ) && (log_info_to[(m,f)] = io)
3071+ (kind== :all || kind== :warn ) && (log_warn_to[(m,f)] = io)
3072+ (kind== :all || kind== :error ) && (log_error_to[(m,f)] = io)
3073+ nothing
3074+ end
3075+
3076+ function logging (; kind:: Symbol = :all )
3077+ depwarn (""" `logging()` is deprecated, use `with_logger` instead to capture
3078+ messages from `Base`""" , :logging )
3079+ (kind== :all || kind== :info ) && empty! (log_info_to)
3080+ (kind== :all || kind== :warn ) && empty! (log_warn_to)
3081+ (kind== :all || kind== :error ) && empty! (log_error_to)
3082+ nothing
3083+ end
3084+
3085+ """
3086+ info([io, ] msg..., [prefix="INFO: "])
3087+
3088+ Display an informational message.
3089+ Argument `msg` is a string describing the information to be displayed.
3090+ The `prefix` keyword argument can be used to override the default
3091+ prepending of `msg`.
3092+
3093+ # Examples
3094+ ```jldoctest
3095+ julia> info("hello world")
3096+ INFO: hello world
3097+
3098+ julia> info("hello world"; prefix="MY INFO: ")
3099+ MY INFO: hello world
3100+ ```
3101+
3102+ See also [`logging`](@ref).
3103+ """
3104+ function info (io:: IO , msg... ; prefix= " INFO: " )
3105+ depwarn (" `info()` is deprecated, use `@info` instead." , :info )
3106+ buf = IOBuffer ()
3107+ iob = redirect (IOContext (buf, io), log_info_to, :info )
3108+ print_with_color (info_color (), iob, prefix; bold = true )
3109+ println_with_color (info_color (), iob, chomp (string (msg... )))
3110+ print (io, String (take! (buf)))
3111+ return
3112+ end
3113+ info (msg... ; prefix= " INFO: " ) = info (STDERR, msg... , prefix= prefix)
3114+
3115+ # print a warning only once
3116+
3117+ const have_warned = Set ()
3118+
3119+ warn_once (io:: IO , msg... ) = warn (io, msg... , once= true )
3120+ warn_once (msg... ) = warn (STDERR, msg... , once= true )
3121+
3122+ """
3123+ warn([io, ] msg..., [prefix="WARNING: ", once=false, key=nothing, bt=nothing, filename=nothing, lineno::Int=0])
3124+
3125+ Display a warning. Argument `msg` is a string describing the warning to be
3126+ displayed. Set `once` to true and specify a `key` to only display `msg` the
3127+ first time `warn` is called. If `bt` is not `nothing` a backtrace is displayed.
3128+ If `filename` is not `nothing` both it and `lineno` are displayed.
3129+
3130+ See also [`logging`](@ref).
3131+ """
3132+ function warn (io:: IO , msg... ;
3133+ prefix= " WARNING: " , once= false , key= nothing , bt= nothing ,
3134+ filename= nothing , lineno:: Int = 0 )
3135+ depwarn (" `warn()` is deprecated, use `@warn` instead." , :warn )
3136+ str = chomp (string (msg... ))
3137+ if once
3138+ if key === nothing
3139+ key = str
3140+ end
3141+ (key in have_warned) && return
3142+ push! (have_warned, key)
3143+ end
3144+ buf = IOBuffer ()
3145+ iob = redirect (IOContext (buf, io), log_warn_to, :warn )
3146+ print_with_color (warn_color (), iob, prefix; bold = true )
3147+ print_with_color (warn_color (), iob, str)
3148+ if bt != = nothing
3149+ show_backtrace (iob, bt)
3150+ end
3151+ if filename != = nothing
3152+ print (iob, " \n in expression starting at $filename :$lineno " )
3153+ end
3154+ println (iob)
3155+ print (io, String (take! (buf)))
3156+ return
3157+ end
3158+
3159+ """
3160+ warn(msg)
3161+
3162+ Display a warning. Argument `msg` is a string describing the warning to be displayed.
3163+
3164+ # Examples
3165+ ```jldoctest
3166+ julia> warn("Beep Beep")
3167+ WARNING: Beep Beep
3168+ ```
3169+ """
3170+ warn (msg... ; kw... ) = warn (STDERR, msg... ; kw... )
3171+
3172+ warn (io:: IO , err:: Exception ; prefix= " ERROR: " , kw... ) =
3173+ warn (io, sprint (showerror, err), prefix= prefix; kw... )
3174+
3175+ warn (err:: Exception ; prefix= " ERROR: " , kw... ) =
3176+ warn (STDERR, err, prefix= prefix; kw... )
3177+
3178+ info (io:: IO , err:: Exception ; prefix= " ERROR: " , kw... ) =
3179+ info (io, sprint (showerror, err), prefix= prefix; kw... )
3180+
3181+ info (err:: Exception ; prefix= " ERROR: " , kw... ) =
3182+ info (STDERR, err, prefix= prefix; kw... )
3183+
29973184# issue #24019
29983185@deprecate similar (a:: AbstractDict ) empty (a)
29993186@deprecate similar (a:: AbstractDict , :: Type{Pair{K,V}} ) where {K, V} empty (a, K, V)
0 commit comments