Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package ocaml-fmt for openSUSE:Factory checked in at 2022-04-06 21:51:14 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ocaml-fmt (Old) and /work/SRC/openSUSE:Factory/.ocaml-fmt.new.1900 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ocaml-fmt" Wed Apr 6 21:51:14 2022 rev:3 rq:967052 version:0.9.0 Changes: -------- --- /work/SRC/openSUSE:Factory/ocaml-fmt/ocaml-fmt.changes 2021-10-18 22:02:04.234088294 +0200 +++ /work/SRC/openSUSE:Factory/.ocaml-fmt.new.1900/ocaml-fmt.changes 2022-04-06 21:51:32.203536140 +0200 @@ -1,0 +2,6 @@ +Mon Apr 4 04:04:04 UTC 2022 - oher...@suse.de + +- Update to version 0.9.0 + See included CHANGES.md for details + +------------------------------------------------------------------- Old: ---- ocaml-fmt-0.8.10.tar.xz New: ---- ocaml-fmt-0.9.0.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ocaml-fmt.spec ++++++ --- /var/tmp/diff_new_pack.XwQMIR/_old 2022-04-06 21:51:32.683530662 +0200 +++ /var/tmp/diff_new_pack.XwQMIR/_new 2022-04-06 21:51:32.687530617 +0200 @@ -1,7 +1,7 @@ # # spec file for package ocaml-fmt # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2022 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,17 +17,17 @@ Name: ocaml-fmt -Version: 0.8.10 +Version: 0.9.0 Release: 0 %{?ocaml_preserve_bytecode} Summary: Format pretty-printer combinators License: ISC Group: Development/Languages/OCaml URL: https://opam.ocaml.org/packages/fmt -Source0: %{name}-%{version}.tar.xz +Source0: %name-%version.tar.xz Patch0: ocaml-fmt.patch BuildRequires: ocaml-dune -BuildRequires: ocaml-rpm-macros >= 20210911 +BuildRequires: ocaml-rpm-macros >= 20220222 BuildRequires: ocaml(ocaml_base_version) >= 4.08 BuildRequires: ocamlfind(cmdliner) BuildRequires: ocamlfind(compiler-libs.toplevel) @@ -40,13 +40,13 @@ Fmt depends only on the OCaml standard library. The optional Fmt_tty library that allows to setup formatters for terminal color output depends on the Unix library. The optional Fmt_cli library that provides command line support for Fmt depends on Cmdliner. %package devel -Summary: Development files for %{name} +Summary: Development files for %name Group: Development/Languages/OCaml -Requires: %{name} = %{version} +Requires: %name = %version %description devel -The %{name}-devel package contains libraries and signature files for -developing applications that use %{name}. +The %name-devel package contains libraries and signature files for +developing applications that use %name. %prep %autosetup -p1 @@ -63,8 +63,8 @@ %check %ocaml_dune_test -%files -f %{name}.files +%files -f %name.files -%files devel -f %{name}.files.devel +%files devel -f %name.files.devel %changelog ++++++ _service ++++++ --- /var/tmp/diff_new_pack.XwQMIR/_old 2022-04-06 21:51:32.719530251 +0200 +++ /var/tmp/diff_new_pack.XwQMIR/_new 2022-04-06 21:51:32.719530251 +0200 @@ -1,7 +1,7 @@ <services> <service name="tar_scm" mode="disabled"> <param name="filename">ocaml-fmt</param> - <param name="revision">11221dcfd08c9b21c2dc63378fd6ffe75333fb33</param> + <param name="revision">f9887faacb29a73a6a41b296a7614bc336f96821</param> <param name="scm">git</param> <param name="submodules">disable</param> <param name="url">https://github.com/dbuenzli/fmt.git</param> ++++++ ocaml-fmt-0.8.10.tar.xz -> ocaml-fmt-0.9.0.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-fmt-0.8.10/B0.ml new/ocaml-fmt-0.9.0/B0.ml --- old/ocaml-fmt-0.8.10/B0.ml 2021-10-03 23:51:57.000000000 +0200 +++ new/ocaml-fmt-0.9.0/B0.ml 2021-10-22 22:13:19.000000000 +0200 @@ -43,6 +43,12 @@ let requires = [ fmt ] in B0_ocaml.exe "test" ~doc:"Test suite" ~srcs ~meta ~requires +let styled_test_bug = + let srcs = Fpath.[`File (v "test/styled_perf_bug.ml")] in + let meta = B0_meta.(empty |> tag test) in + let requires = [unix; fmt] in + B0_ocaml.exe "styled_perf_bug" ~srcs ~meta ~requires + (* Packs *) let default = diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-fmt-0.8.10/CHANGES.md new/ocaml-fmt-0.9.0/CHANGES.md --- old/ocaml-fmt-0.8.10/CHANGES.md 2021-10-03 23:51:57.000000000 +0200 +++ new/ocaml-fmt-0.9.0/CHANGES.md 2021-10-22 22:13:19.000000000 +0200 @@ -1,3 +1,20 @@ +v0.9.0 2021-10-22 Zagreb +------------------------ + +* Add alert messages to deprecation annotations (#47). +* The solution using ephemerons introduced in v0.8.7 for attaching + custom data to formatters has unreliable performance characteristics + in some usage scenarios. Namely use of `Fmt.styled` with + `Fmt.[k]str` heavy code as those rely on `Format.{k,a}sprintf` which + allocate one formatter per call. + + Hence we subvert again the `Format` tag system to do dirty + things. However since as of 4.08 tags became an extensible sum type + we can keep our dirty things entirely internal. + + Thanks to Thomas Leonard for reporting and David Kaloper Mer??injak + for further investigations (#52). + v0.8.10 2021-10-04 Zagreb ------------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-fmt-0.8.10/_tags new/ocaml-fmt-0.9.0/_tags --- old/ocaml-fmt-0.8.10/_tags 2021-10-03 23:51:57.000000000 +0200 +++ new/ocaml-fmt-0.9.0/_tags 2021-10-22 22:13:19.000000000 +0200 @@ -5,3 +5,4 @@ <src/fmt_cli*> : package(cmdliner) <src/fmt_top*> : package(compiler-libs.toplevel) <test> : include +<test/styled_perf_bug*> : package(unix) \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-fmt-0.8.10/pkg/pkg.ml new/ocaml-fmt-0.9.0/pkg/pkg.ml --- old/ocaml-fmt-0.8.10/pkg/pkg.ml 2021-10-03 23:51:57.000000000 +0200 +++ new/ocaml-fmt-0.9.0/pkg/pkg.ml 2021-10-22 22:13:19.000000000 +0200 @@ -15,4 +15,6 @@ Pkg.mllib ~cond:cmdliner "src/fmt_cli.mllib"; Pkg.mllib ~api:[] "src/fmt_top.mllib"; Pkg.lib "src/fmt_tty_top_init.ml"; - Pkg.test "test/test"; ] + Pkg.test "test/test"; + Pkg.test "test/styled_perf_bug"; + ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-fmt-0.8.10/src/fmt.ml new/ocaml-fmt-0.9.0/src/fmt.ml --- old/ocaml-fmt-0.8.10/src/fmt.ml 2021-10-03 23:51:57.000000000 +0200 +++ new/ocaml-fmt-0.9.0/src/fmt.ml 2021-10-22 22:13:19.000000000 +0200 @@ -599,59 +599,67 @@ (* Conditional UTF-8 and styled formatting. *) -type any = .. -type 'a attr = int * ('a -> any) * (any -> 'a) +module Imap = Map.Make (Int) +type 'a attr = int * ('a -> string) * (string -> 'a) let id = ref 0 -let attr (type a) () = - incr id; - let module M = struct type any += K of a end in - !id, (fun x -> M.K x), (function M.K x -> x | _ -> assert false) - -module Int = struct type t = int let compare a b = compare (a: int) b end -module Imap = Map.Make (Int) +let attr (type a) enc dec = incr id; (!id, enc, dec) -let attrs = ref [] -let store ppf = - let open Ephemeron.K1 in - let rec go ppf top = function - | [] -> - let e = create () and v = ref Imap.empty in - attrs := e :: List.rev top; set_key e ppf; set_data e v; v - | e::es -> - match get_key e with - | None -> go ppf top es - | Some k when not (k == ppf) -> go ppf (e::top) es - | Some k -> - let v = match get_data e with Some v -> v | _ -> assert false in - if not (top == []) then attrs := e :: List.rev_append top es; - ignore (Sys.opaque_identity k); v - in - go ppf [] !attrs +type Format.stag += +| Fmt_store_get : 'a attr -> Format.stag +| Fmt_store_set : 'a attr * 'a -> Format.stag + +let store () = + let s = ref Imap.empty in + fun ~other -> function + | Fmt_store_get (id, _, _) -> Option.value ~default:"" (Imap.find_opt id !s) + | Fmt_store_set ((id, enc, _), v) -> s := Imap.add id (enc v) !s; "ok" + | stag -> other stag + +let setup_store ppf = + let funs = Format.pp_get_formatter_stag_functions ppf () in + let mark_open_stag = store () ~other:funs.mark_open_stag in + Format.pp_set_formatter_stag_functions ppf { funs with mark_open_stag } + +let store_op op ppf = + let funs = Format.pp_get_formatter_stag_functions ppf () in + funs.mark_open_stag op -let get (k, _, prj) ppf = - match Imap.find_opt k !(store ppf) with Some x -> Some (prj x) | _ -> None +let get (_, _, dec as attr) ppf = match store_op (Fmt_store_get attr) ppf with +| "" -> None | s -> Some (dec s) -let set (k, inj, _) v ppf = - if ppf == Format.str_formatter then invalid_arg' err_str_formatter else - let s = store ppf in - s := Imap.add k (inj v) !s +let rec set attr v ppf = match store_op (Fmt_store_set (attr, v)) ppf with +| "ok" -> () | _ -> setup_store ppf; set attr v ppf let def x = function Some y -> y | _ -> x -let utf_8_attr = attr () +let utf_8_attr = + let enc = function true -> "t" | false -> "f" in + let dec = function "t" -> true | "f" -> false | _ -> assert false in + attr enc dec + let utf_8 ppf = get utf_8_attr ppf |> def true let set_utf_8 ppf x = set utf_8_attr x ppf type style_renderer = [ `Ansi_tty | `None ] -let style_renderer_attr = attr () +let style_renderer_attr = + let enc = function `Ansi_tty -> "A" | `None -> "N" in + let dec = function "A" -> `Ansi_tty | "N" -> `None | _ -> assert false in + attr enc dec + let style_renderer ppf = get style_renderer_attr ppf |> def `None let set_style_renderer ppf x = set style_renderer_attr x ppf let with_buffer ?like buf = let ppf = Format.formatter_of_buffer buf in - (match like with Some like -> store ppf := !(store like) | _ -> ()); - ppf + (* N.B. this does slighty more it also makes buf use other installed + semantic tag actions. *) + match like with + | None -> ppf + | Some like -> + let funs = Format.pp_get_formatter_stag_functions like () in + Format.pp_set_formatter_stag_functions ppf funs; + ppf let str_like ppf fmt = let buf = Buffer.create 64 in @@ -732,23 +740,28 @@ Format.pp_print_as ppf 0 style; Format.pp_print_as ppf 0 "m" -let curr_style = attr () +let curr_style = attr Fun.id Fun.id let styled style pp_v ppf v = match style_renderer ppf with | `None -> pp_v ppf v | `Ansi_tty -> - let curr = match get curr_style ppf with - | None -> let s = ref "0" in set curr_style s ppf; s + let prev = match get curr_style ppf with + | None -> let zero = "0" in set curr_style zero ppf; zero | Some s -> s in - let prev = !curr and here = ansi_style_code style in - curr := (match style with `None -> here | _ -> prev ^ ";" ^ here); - try pp_sgr ppf here; pp_v ppf v; pp_sgr ppf prev; curr := prev with - | e -> curr := prev; raise e + let here = ansi_style_code style in + let curr = match style with + | `None -> here + | _ -> String.concat ";" [prev; here] + in + let finally () = set curr_style prev ppf in + set curr_style curr ppf; + Fun.protect ~finally @@ fun () -> + pp_sgr ppf here; pp_v ppf v; pp_sgr ppf prev (* Records *) -external id : 'a -> 'a = "%identity" +let id = Fun.id let label = styled (`Fg `Yellow) string let field ?(label = label) ?(sep = any ":@ ") l prj pp_v ppf v = pf ppf "@[<1>%a%a%a@]" label l sep () pp_v (prj v) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-fmt-0.8.10/src/fmt.mli new/ocaml-fmt-0.9.0/src/fmt.mli --- old/ocaml-fmt-0.8.10/src/fmt.mli 2021-10-03 23:51:57.000000000 +0200 +++ new/ocaml-fmt-0.9.0/src/fmt.mli 2021-10-22 22:13:19.000000000 +0200 @@ -624,37 +624,37 @@ (** {1:deprecated Deprecated} *) val strf : ('a, Format.formatter, unit, string) format4 -> 'a -[@@ocaml.deprecated] +[@@ocaml.deprecated "use Fmt.str instead."] (** @deprecated use {!str} instead. *) val kstrf : (string -> 'a) -> ('b, Format.formatter, unit, 'a) format4 -> 'b -[@@ocaml.deprecated] +[@@ocaml.deprecated "use Fmt.kstr instead."] (** @deprecated use {!kstr} instead. *) val strf_like : Format.formatter -> ('a, Format.formatter, unit, string) format4 -> 'a -[@@ocaml.deprecated] +[@@ocaml.deprecated "use Fmt.str_like instead."] (** @deprecated use {!str_like} instead. *) val always : (unit, Format.formatter, unit) Stdlib.format -> 'a t -[@@ocaml.deprecated] +[@@ocaml.deprecated "use Fmt.any instead."] (** @deprecated use {!any} instead. *) val unit : (unit, Format.formatter, unit) Stdlib.format -> unit t -[@@ocaml.deprecated] +[@@ocaml.deprecated "use Fmt.any instead."] (** @deprecated use {!any}. *) val prefix : unit t -> 'a t -> 'a t -[@@ocaml.deprecated] +[@@ocaml.deprecated "use Fmt.(++) instead."] (** @deprecated use {!( ++ )}. *) val suffix : unit t -> 'a t -> 'a t -[@@ocaml.deprecated] +[@@ocaml.deprecated "use Fmt.(++) instead."] (** @deprecated use {!( ++ )}. *) val styled_unit : style -> (unit, Format.formatter, unit) Stdlib.format -> unit t -[@@ocaml.deprecated] +[@@ocaml.deprecated "use Fmt.(styled s (any fmt)) instead."] (** @deprecated use [styled s (any fmt)] instead *) (** {1:nameconv Naming conventions} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ocaml-fmt-0.8.10/test/styled_perf_bug.ml new/ocaml-fmt-0.9.0/test/styled_perf_bug.ml --- old/ocaml-fmt-0.8.10/test/styled_perf_bug.ml 1970-01-01 01:00:00.000000000 +0100 +++ new/ocaml-fmt-0.9.0/test/styled_perf_bug.ml 2021-10-22 22:13:19.000000000 +0200 @@ -0,0 +1,11 @@ +let n = 10000 + +let () = + while true do + let t0 = Unix.gettimeofday () in + for _i = 1 to n do + ignore @@ Fmt.str "Hello %a" Fmt.string "world" + done; + let t1 = Unix.gettimeofday () in + Printf.printf "Formatted %.0f messages/second\n%!" (float n /. (t1 -. t0)) + done