Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package ocaml-pyml for openSUSE:Factory 
checked in at 2021-10-13 18:06:05
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ocaml-pyml (Old)
 and      /work/SRC/openSUSE:Factory/.ocaml-pyml.new.2443 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ocaml-pyml"

Wed Oct 13 18:06:05 2021 rev:3 rq:923490 version:20210924

Changes:
--------
--- /work/SRC/openSUSE:Factory/ocaml-pyml/ocaml-pyml.changes    2021-06-25 
15:02:01.632202023 +0200
+++ /work/SRC/openSUSE:Factory/.ocaml-pyml.new.2443/ocaml-pyml.changes  
2021-10-13 18:10:00.227643006 +0200
@@ -1,0 +2,12 @@
+Sat Sep 25 20:58:01 UTC 2021 - Matej Cepl <[email protected]>
+
+- Don't use python(abi) construct it is not reliably supported in
+  openSUSE. Related to bsc#1187262
+
+-------------------------------------------------------------------
+Sat Sep 11 12:34:56 UTC 2021 - [email protected]
+
+- Update to version 20210924
+  build with dune
+
+-------------------------------------------------------------------

Old:
----
  ocaml-pyml-20210226.tar.xz

New:
----
  ocaml-pyml-20210924.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ ocaml-pyml.spec ++++++
--- /var/tmp/diff_new_pack.RnLcsL/_old  2021-10-13 18:10:00.663643689 +0200
+++ /var/tmp/diff_new_pack.RnLcsL/_new  2021-10-13 18:10:00.667643695 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package ocaml-pyml
 #
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2021 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -15,8 +15,9 @@
 # Please submit bugfixes or comments via https://bugs.opensuse.org/
 #
 
+
 Name:           ocaml-pyml
-Version:        20210226
+Version:        20210924
 Release:        0
 %{?ocaml_preserve_bytecode}
 Summary:        Stdcompat: compatibility module for OCaml standard library 
@@ -25,19 +26,18 @@
 URL:            https://opam.ocaml.org/packages/pyml
 Source0:        %{name}-%{version}.tar.xz
 BuildRequires:  ocaml
-#uildRequires:  ocaml-dune
-BuildRequires:  ocaml-rpm-macros >= 20210409
+BuildRequires:  ocaml-dune >= 2.8
+BuildRequires:  ocaml-rpm-macros >= 20210911
 BuildRequires:  ocamlfind(bigarray)
-BuildRequires:  ocamlfind(findlib)
 BuildRequires:  ocamlfind(stdcompat)
 BuildRequires:  ocamlfind(unix)
 # make check
-BuildRequires:  python(abi) > 3.0
 %if 0%{?suse_version} > 1315
 BuildRequires:  python3-numpy
 %else
 BuildRequires:  python-numpy
 %endif
+BuildRequires:  which
 
 %description
 Stdcompat is a compatibility layer allowing programs to use some recent 
additions to the OCaml standard library while preserving the ability to be 
compiled on former versions of OCaml.
@@ -46,7 +46,7 @@
 Summary:        Development files for %{name}
 Group:          Development/Languages/OCaml
 Requires:       %{name} = %{version}
-
+Requires:       which
 
 %description    devel
 The %{name}-devel package contains libraries and signature files for
@@ -56,33 +56,16 @@
 %autosetup -p1
 
 %build
-sed -i~ '
-s@^\(HAVE_OCAMLFIND := $(shell \).*@\1 set -x ; \\@
-s@2>&1@@g
-' Makefile
-diff -u "$_"~ "$_" && exit 1
-%make_build
-%if 0
 dune_release_pkgs='pyml'
 %ocaml_dune_setup
 %ocaml_dune_build
-%endif
 
 %install
-mkdir -vp '%{buildroot}%{ocaml_standard_library}'
-export OCAMLFIND_DESTDIR='%{buildroot}%{ocaml_standard_library}'
-export OCAMLFIND_LDCONF='ignore'
-%make_install STDCOMPAT="$(ocamlfind query stdcompat)"
-%ocaml_create_file_list
-%if 0
 %ocaml_dune_install
 %ocaml_create_file_list
-%endif
 
 %check
-%if 0
 %ocaml_dune_test
-%endif
 
 %files -f %{name}.files
 

++++++ _service ++++++
--- /var/tmp/diff_new_pack.RnLcsL/_old  2021-10-13 18:10:00.691643733 +0200
+++ /var/tmp/diff_new_pack.RnLcsL/_new  2021-10-13 18:10:00.695643739 +0200
@@ -1,7 +1,7 @@
 <services>
   <service name="tar_scm" mode="disabled">
     <param name="filename">ocaml-pyml</param>
-    <param name="revision">b6608db88f0559f7e59b9be859a649f5bb6812b7</param>
+    <param name="revision">8521e337944b651db2eb791ef561348d0ecfcf7a</param>
     <param name="scm">git</param>
     <param name="submodules">disable</param>
     <param name="url">https://github.com/thierry-martinez/pyml.git</param>

++++++ ocaml-pyml-20210226.tar.xz -> ocaml-pyml-20210924.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ocaml-pyml-20210226/.gitignore 
new/ocaml-pyml-20210924/.gitignore
--- old/ocaml-pyml-20210226/.gitignore  1970-01-01 01:00:00.000000000 +0100
+++ new/ocaml-pyml-20210924/.gitignore  2021-09-29 10:00:10.000000000 +0200
@@ -0,0 +1,23 @@
+_build
+.merlin
+.depend
+*.cm[aioxt]
+*.cmti
+*.cmx[as]
+*.[ao]
+*.so
+*.swp
+*~
+*.inc
+/generate
+/pyml.h
+/pyml_libdir.ml
+/pyml_compat.ml
+/pyml_arch.ml
+/pywrappers.mli
+/pywrappers.ml
+/pymlutop
+/pyml_tests.bytecode
+/numpy_tests.bytecode
+/pyml_tests.native
+/numpy_tests.native
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ocaml-pyml-20210226/CHANGES.md 
new/ocaml-pyml-20210924/CHANGES.md
--- old/ocaml-pyml-20210226/CHANGES.md  2021-02-26 23:10:52.000000000 +0100
+++ new/ocaml-pyml-20210924/CHANGES.md  2021-09-29 10:00:10.000000000 +0200
@@ -1,5 +1,32 @@
 [*] marks changes that break compatibility with previous versions.
 
+# 2021-09-24
+
+- Use `dune` as default build system
+  (dunification done by Laurent Mazare, 
https://github.com/thierry-martinez/pyml/pull/28)
+
+  This should in particular fix build problems of reverse dependencies
+  with the byte-code compiler
+  (reported by @nicoTolly, https://github.com/thierry-martinez/pyml/issues/62)
+
+    - Handle more platforms with dune
+      (reported by Olaf Hering, 
https://github.com/thierry-martinez/pyml/issues/68)
+
+    - `pyutils` is no longer used by generate and is shipped with `pyml` 
package
+      as it was the case with Makefile-based build system
+      (reported by Olaf Hering, 
https://github.com/thierry-martinez/pyml/issues/69)
+
+- Support for raising exceptions with traceback from OCaml
+  (implemented by Laurent Mazare, 
https://github.com/thierry-martinez/pyml/pull/65)
+
+- Fix soundness bug with `numpy`
+  (reported by Richard Alligier, 
https://github.com/thierry-martinez/pyml/pull/65)
+
+- Fix `Py.Array.numpy` arrays on 32-bit platforms
+  (reported by Olaf Hering, https://github.com/thierry-martinez/pyml/pull/70)
+
+- Fix soundness bug on strings with OCaml <4.06 (reported by OCaml CI)
+
 # 2021-02-26
 
 - Compatibility with Python 3.10 (reported by Richard W.M. Jones)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ocaml-pyml-20210226/Makefile 
new/ocaml-pyml-20210924/Makefile
--- old/ocaml-pyml-20210226/Makefile    2021-02-26 23:10:52.000000000 +0100
+++ new/ocaml-pyml-20210924/Makefile    2021-09-29 10:00:10.000000000 +0200
@@ -356,3 +356,9 @@
 #      $(OCAMLMKTOP) -o $@ -thread -linkpkg -package utop -dontlink 
compiler-libs $^
        ocamlfind ocamlc -thread -linkpkg -linkall -predicates create_toploop \
                -package compiler-libs.toplevel,utop,stdcompat $^ -o $@
+
+pyops.ml: pyops.ml.new
+       cp $< $@
+
+pyops.mli: pyops.mli.new
+       cp $< $@
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ocaml-pyml-20210226/dune new/ocaml-pyml-20210924/dune
--- old/ocaml-pyml-20210226/dune        2021-02-26 23:10:52.000000000 +0100
+++ new/ocaml-pyml-20210924/dune        2021-09-29 10:00:10.000000000 +0200
@@ -1,20 +1,14 @@
 (library
-  (name pyml)
-  (modules numpy py pycaml pyml_arch pytypes pywrappers)
-  (c_names numpy_stubs pyml_stubs)
+  (public_name pyml)
+  (modules numpy py pyops pycaml pyml_arch pytypes pywrappers pyutils)
+  (foreign_stubs (language c) (names numpy_stubs pyml_stubs))
   (wrapped false)
-  (libraries bigarray stdcompat pyutils))
+  (libraries bigarray stdcompat))
 
 (executables
   (names generate)
   (modules generate)
-  (libraries stdcompat pyutils))
-
-(library
-  (name pyutils)
-  (modules pyutils)
-  (wrapped false)
-  (libraries stdcompat unix))
+  (libraries stdcompat))
 
 (rule
   (targets pywrappers.ml pyml.h pyml_dlsyms.inc pyml_wrappers.inc)
@@ -22,22 +16,60 @@
   (action (run %{gen})))
 
 (rule
-  (targets pyml_arch.ml)
-  (deps (:pyml_arch pyml_arch_%{ocaml-config:system}.ml))
-  (action (copy %{pyml_arch} pyml_arch.ml)))
+  (target pyml_arch.ml)
+  (deps pyml_arch%{ocaml-config:ext_dll}.ml)
+  (action (copy %{deps} %{target})))
+
+(rule
+  (target pyml_arch.so.ml)
+  (deps pyml_arch_unix.ml)
+  (action (copy %{deps} %{target})))
+
+(rule
+  (target pyml_arch.dylib.ml)
+  (deps pyml_arch_darwin.ml)
+  (action (copy %{deps} %{target})))
+
+(rule
+  (target pyml_arch.dll.ml)
+  (deps pyml_arch_cygwin.ml)
+  (action (copy %{deps} %{target})))
 
 (library
   (name pyml_tests_common)
   (modules pyml_tests_common)
-  (wrapped false)
   (libraries pyml stdcompat))
 
 (test
   (name numpy_tests)
   (modules numpy_tests)
-  (libraries pyml pyml_tests_common stdcompat pyutils))
+  (libraries pyml pyml_tests_common stdcompat))
 
 (test
   (name pyml_tests)
   (modules pyml_tests)
-  (libraries pyml pyml_tests_common stdcompat pyutils))
+  (libraries pyml pyml_tests_common stdcompat))
+
+(rule
+  (enabled_if (>= %{ocaml_version} 4.06))
+  (target pyops.mli)
+  (deps pyops.mli.new)
+  (action (copy %{deps} %{target})))
+
+(rule
+  (enabled_if (>= %{ocaml_version} 4.06))
+  (target pyops.ml)
+  (deps pyops.ml.new)
+  (action (copy %{deps} %{target})))
+
+(rule
+  (enabled_if (< %{ocaml_version} 4.06))
+  (target pyops.mli)
+  (deps pyops.mli.405)
+  (action (copy %{deps} %{target})))
+
+(rule
+  (enabled_if (< %{ocaml_version} 4.06))
+  (target pyops.ml)
+  (deps pyops.ml.405)
+  (action (copy %{deps} %{target})))
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ocaml-pyml-20210226/dune-project 
new/ocaml-pyml-20210924/dune-project
--- old/ocaml-pyml-20210226/dune-project        2021-02-26 23:10:52.000000000 
+0100
+++ new/ocaml-pyml-20210924/dune-project        2021-09-29 10:00:10.000000000 
+0200
@@ -1 +1 @@
-(lang dune 1.6)
+(lang dune 2.5)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ocaml-pyml-20210226/generate.ml 
new/ocaml-pyml-20210924/generate.ml
--- old/ocaml-pyml-20210226/generate.ml 2021-02-26 23:10:52.000000000 +0100
+++ new/ocaml-pyml-20210924/generate.ml 2021-09-29 10:00:10.000000000 +0200
@@ -143,10 +143,6 @@
      arguments = Fun [];
      result = Unit;
      optional = false; };
-   { symbol = "PyErr_Restore";
-     arguments = Fun [PyObject false; PyObject false; PyObject false];
-     result = Unit;
-     optional = false; };
    { symbol = "PyErr_PrintEx";
      arguments = Fun [Int];
      result = Unit;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ocaml-pyml-20210226/numpy_tests.ml 
new/ocaml-pyml-20210924/numpy_tests.ml
--- old/ocaml-pyml-20210226/numpy_tests.ml      2021-02-26 23:10:52.000000000 
+0100
+++ new/ocaml-pyml-20210924/numpy_tests.ml      2021-09-29 10:00:10.000000000 
+0200
@@ -26,6 +26,37 @@
         end)
 
 let () =
+  Pyml_tests_common.add_test ~title:"of_bigarray2"
+    (fun () ->
+      if Py.Import.try_import_module "numpy" = None then
+        Pyml_tests_common.Disabled "numpy is not available"
+      else
+        begin
+          let array = [| [| 1.; 2.; 3. |]; [| -1.23; Stdcompat.Float.nan; 2.72 
|] |] in
+          let array2 =
+            Bigarray.Array2.of_array (Bigarray.float64) (Bigarray.c_layout) 
array in
+          let bigarray = Bigarray.genarray_of_array2 array2 in
+          let a = Numpy.of_bigarray bigarray in
+          let m = Py.Import.add_module "test" in
+          Py.Module.set m "array" a;
+          assert (Py.Run.simple_string "
+from test import array
+import numpy
+
+assert list(array.shape) == [2, 3]
+numpy.testing.assert_almost_equal(array[0], [1, 2, 3])
+assert(numpy.isnan(array[1, 1]))
+array[0, 0] = 42.
+array[0, 1] = 43.
+array[1, 1] = 1.
+");
+          assert (Bigarray.Array2.get array2 0 0 = 42.);
+          assert (Bigarray.Array2.get array2 0 1 = 43.);
+          assert (Bigarray.Array2.get array2 1 1 = 1.);
+          Pyml_tests_common.Passed
+        end)
+
+let () =
   Pyml_tests_common.add_test ~title:"to_bigarray"
     (fun () ->
       if Py.Import.try_import_module "numpy" = None then
@@ -36,6 +67,7 @@
           let callback arg =
             let bigarray =
               Numpy.to_bigarray Bigarray.nativeint Bigarray.c_layout arg.(0) in
+            assert (Bigarray.Genarray.dims bigarray = [| 4 |]);
             let array1 = Bigarray.array1_of_genarray bigarray in
             assert (Bigarray.Array1.get array1 0 = 0n);
             assert (Bigarray.Array1.get array1 1 = 1n);
@@ -50,6 +82,46 @@
 ");
           Pyml_tests_common.Passed
         end)
+
+let assert_almost_eq ?(eps = 1e-7) f1 f2 =
+  if Stdcompat.Float.abs (f1 -. f2) > eps then
+    failwith (Printf.sprintf "%f <> %f" f1 f2)
+
+let () =
+  Pyml_tests_common.add_test ~title:"to_bigarray2"
+    (fun () ->
+      if Py.Import.try_import_module "numpy" = None then
+        Pyml_tests_common.Disabled "numpy is not available"
+      else
+        begin
+          let m = Py.Import.add_module "test" in
+          let callback arg =
+            let bigarray =
+              Numpy.to_bigarray Bigarray.float32 Bigarray.c_layout arg.(0) in
+            assert (Bigarray.Genarray.dims bigarray = [| 2; 4 |]);
+            let array2 = Bigarray.array2_of_genarray bigarray in
+            let assert_almost_eq i j v =
+              assert_almost_eq (Bigarray.Array2.get array2 i j) v in
+            let assert_is_nan i j =
+              let v = Bigarray.Array2.get array2 i j in
+              assert (Stdcompat.Float.is_nan v) in
+            assert_almost_eq 0 0 0.12;
+            assert_almost_eq 0 1 1.23;
+            assert_almost_eq 0 2 2.34;
+            assert_almost_eq 0 3 3.45;
+            assert_almost_eq 1 0 (-1.);
+            assert_is_nan 1 1;
+            assert_almost_eq 1 2 1.;
+            assert_almost_eq 1 3 0.;
+            Py.none in
+          Py.Module.set m "callback" (Py.Callable.of_function callback);
+          assert (Py.Run.simple_string "
+from test import callback
+import numpy
+callback(numpy.array([[0.12,1.23,2.34,3.45],[-1.,numpy.nan,1.,0.]], 
dtype=numpy.float32))
+");
+          Pyml_tests_common.Passed
+        end)
 
 let assert_invalid_argument f =
   try
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ocaml-pyml-20210226/py.ml 
new/ocaml-pyml-20210924/py.ml
--- old/ocaml-pyml-20210226/py.ml       2021-02-26 23:10:52.000000000 +0100
+++ new/ocaml-pyml-20210924/py.ml       2021-09-29 10:00:10.000000000 +0200
@@ -34,6 +34,8 @@
   -> pyobject = "PyObject_CallMethodObjArgs_wrapper"
 external pyerr_fetch_internal: unit -> pyobject * pyobject * pyobject
     = "PyErr_Fetch_wrapper"
+external pyerr_restore_internal: pyobject -> pyobject -> pyobject -> unit
+    = "PyErr_Restore_wrapper"
 external pystring_asstringandsize: pyobject -> string option
     = "PyString_AsStringAndSize_wrapper"
 external pyobject_ascharbuffer: pyobject -> string option
@@ -48,6 +50,8 @@
       = "Python27_PyCapsule_IsValid_wrapper"
 external pycapsule_check: Pytypes.pyobject -> int
       = "pyml_capsule_check"
+external pyframe_new : string -> string -> int -> Pytypes.pyobject
+      = "pyml_pyframe_new"
 
 external ucs: unit -> ucs = "py_get_UCS"
 (* Avoid warning 32. *)
@@ -1307,7 +1311,7 @@
   let print_ex i =
     Pywrappers.pyerr_printex i
 
-  let restore = Pywrappers.pyerr_restore
+  let restore = pyerr_restore_internal
 
   let restore_tuple (ptype, pvalue, ptraceback) =
     restore ptype pvalue ptraceback
@@ -1328,41 +1332,41 @@
 
   let set_object = Pywrappers.pyerr_setobject
 
+  let of_error = function
+      Exception -> Pywrappers.pyexc_exception ()
+    | StandardError ->
+        if !version_major_value <= 2 then
+          Pywrappers.Python2.pyexc_standarderror ()
+        else
+          Pywrappers.pyexc_exception ()
+    | ArithmeticError -> Pywrappers.pyexc_arithmeticerror ()
+    | LookupError -> Pywrappers.pyexc_lookuperror ()
+    | AssertionError -> Pywrappers.pyexc_assertionerror ()
+    | AttributeError -> Pywrappers.pyexc_attributeerror ()
+    | EOFError -> Pywrappers.pyexc_eoferror ()
+    | EnvironmentError -> Pywrappers.pyexc_environmenterror ()
+    | FloatingPointError -> Pywrappers.pyexc_floatingpointerror ()
+    | IOError -> Pywrappers.pyexc_ioerror ()
+    | ImportError -> Pywrappers.pyexc_importerror ()
+    | IndexError -> Pywrappers.pyexc_indexerror ()
+    | KeyError -> Pywrappers.pyexc_keyerror ()
+    | KeyboardInterrupt -> Pywrappers.pyexc_keyboardinterrupt ()
+    | MemoryError -> Pywrappers.pyexc_memoryerror ()
+    | NameError -> Pywrappers.pyexc_nameerror ()
+    | NotImplementedError -> Pywrappers.pyexc_notimplementederror ()
+    | OSError -> Pywrappers.pyexc_oserror ()
+    | OverflowError -> Pywrappers.pyexc_overflowerror ()
+    | ReferenceError -> Pywrappers.pyexc_referenceerror ()
+    | RuntimeError -> Pywrappers.pyexc_runtimeerror ()
+    | SyntaxError -> Pywrappers.pyexc_syntaxerror ()
+    | SystemExit -> Pywrappers.pyexc_systemerror ()
+    | TypeError -> Pywrappers.pyexc_typeerror ()
+    | ValueError -> Pywrappers.pyexc_valueerror ()
+    | ZeroDivisionError -> Pywrappers.pyexc_zerodivisionerror ()
+    | StopIteration -> Pywrappers.pyexc_stopiteration ()
+
   let set_error error msg =
-    let exc =
-      match error with
-        Exception -> Pywrappers.pyexc_exception ()
-      | StandardError ->
-          if !version_major_value <= 2 then
-            Pywrappers.Python2.pyexc_standarderror ()
-          else
-            Pywrappers.pyexc_exception ()
-      | ArithmeticError -> Pywrappers.pyexc_arithmeticerror ()
-      | LookupError -> Pywrappers.pyexc_lookuperror ()
-      | AssertionError -> Pywrappers.pyexc_assertionerror ()
-      | AttributeError -> Pywrappers.pyexc_attributeerror ()
-      | EOFError -> Pywrappers.pyexc_eoferror ()
-      | EnvironmentError -> Pywrappers.pyexc_environmenterror ()
-      | FloatingPointError -> Pywrappers.pyexc_floatingpointerror ()
-      | IOError -> Pywrappers.pyexc_ioerror ()
-      | ImportError -> Pywrappers.pyexc_importerror ()
-      | IndexError -> Pywrappers.pyexc_indexerror ()
-      | KeyError -> Pywrappers.pyexc_keyerror ()
-      | KeyboardInterrupt -> Pywrappers.pyexc_keyboardinterrupt ()
-      | MemoryError -> Pywrappers.pyexc_memoryerror ()
-      | NameError -> Pywrappers.pyexc_nameerror ()
-      | NotImplementedError -> Pywrappers.pyexc_notimplementederror ()
-      | OSError -> Pywrappers.pyexc_oserror ()
-      | OverflowError -> Pywrappers.pyexc_overflowerror ()
-      | ReferenceError -> Pywrappers.pyexc_referenceerror ()
-      | RuntimeError -> Pywrappers.pyexc_runtimeerror ()
-      | SyntaxError -> Pywrappers.pyexc_syntaxerror ()
-      | SystemExit -> Pywrappers.pyexc_systemerror ()
-      | TypeError -> Pywrappers.pyexc_typeerror ()
-      | ValueError -> Pywrappers.pyexc_valueerror ()
-      | ZeroDivisionError -> Pywrappers.pyexc_zerodivisionerror ()
-      | StopIteration -> Pywrappers.pyexc_stopiteration () in
-    set_object exc (String.of_string msg)
+    set_object (of_error error) (String.of_string msg)
 end
 
 exception Err of Err.t * string
@@ -2017,6 +2021,33 @@
   let of_list = of_list_map id
 end
 
+module Traceback = struct
+  type frame =
+    { filename : string
+    ; function_name : string
+    ; line_number : int
+    }
+
+  let create_frame { filename; function_name; line_number } =
+    check_not_null (pyframe_new filename function_name line_number)
+
+  type t = frame list
+
+  let create t =
+    let types_module = check_not_null (Pywrappers.pyimport_importmodule 
"types") in
+    let tb_type = Object.find_attr_string types_module "TracebackType" in
+    List.fold_left
+      (fun acc frame ->
+        let args =
+          Tuple.of_array [| acc; create_frame frame; Int.of_int 0; Int.of_int 
frame.line_number |]
+        in
+        Eval.call_object tb_type args)
+      none
+      t
+end
+
+exception Err_with_traceback of Err.t * string * Traceback.t
+
 module Callable = struct
   let check v = Pywrappers.pycallable_check v <> 0
 
@@ -2025,9 +2056,21 @@
       E (errtype, errvalue) ->
         Err.set_object errtype errvalue;
         null
-    | Err (errtype, msg) ->
+    | Err (errtype, msg)
+    | Err_with_traceback (errtype, msg, []) ->
         Err.set_error errtype msg;
         null
+    | Err_with_traceback (errtype, msg, traceback) ->
+        let () =
+          (* Traceback objects can only be created since Python 3.7. *)
+          if !version_major_value <= 2 || (!version_major_value == 3 && 
!version_minor_value < 7)
+          then
+            Err.set_error errtype msg
+          else
+            let traceback = Traceback.create traceback in
+            Err.restore (Err.of_error errtype) (String.of_string msg) 
traceback;
+        in
+        null
 
   let of_function_as_tuple ?name ?(docstring = "Anonymous closure") f =
     check_not_null (pywrap_closure name docstring
@@ -2119,11 +2162,6 @@
 
 let import_opt = Import.import_module_opt
 
-let option_map f o =
-  match o with
-  | None -> None
-  | Some x -> Some (f x)
-
 module Module = struct
   let check o = Type.get o = Type.Module
 
@@ -2147,13 +2185,13 @@
 
   let get_function m name = Callable.to_function (get m name)
 
-  let get_function_opt m name = option_map Callable.to_function (get_opt m 
name)
+  let get_function_opt m name = Option.map Callable.to_function (get_opt m 
name)
 
   let get_function_with_keywords m name =
     Callable.to_function_with_keywords (get m name)
 
   let get_function_with_keywords_opt m name =
-    option_map Callable.to_function_with_keywords (get_opt m name)
+    Option.map Callable.to_function_with_keywords (get_opt m name)
 
   let set_function m name f = set m name (Callable.of_function f)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ocaml-pyml-20210226/py.mli 
new/ocaml-pyml-20210924/py.mli
--- old/ocaml-pyml-20210226/py.mli      2021-02-26 23:10:52.000000000 +0100
+++ new/ocaml-pyml-20210924/py.mli      2021-09-29 10:00:10.000000000 +0200
@@ -861,9 +861,24 @@
       instead. *)
 end
 
+module Traceback : sig
+  type frame =
+    { filename : string
+    ; function_name : string
+    ; line_number : int
+    }
+
+  val create_frame : frame -> Object.t
+
+  type t = frame list
+end
+
 exception Err of Err.t * string
 (** Represents an exception to be set with {!Err.set_error} in a callback. *)
 
+exception Err_with_traceback of Err.t * string * Traceback.t
+(** Represents an exception with traceback information to be set with 
{!Err.restore}. *)
+
 module Eval: sig
   val call_object: Object.t -> Object.t -> Object.t
  (** See {{:https://docs.python.org/3.0/extending/extending.html} Extending 
Python with C or C++} *)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ocaml-pyml-20210226/pycaml.mli 
new/ocaml-pyml-20210924/pycaml.mli
--- old/ocaml-pyml-20210226/pycaml.mli  2021-02-26 23:10:52.000000000 +0100
+++ new/ocaml-pyml-20210924/pycaml.mli  2021-09-29 10:00:10.000000000 +0200
@@ -707,7 +707,6 @@
 val pyerr_occurred : unit -> pyobject
 val pyerr_clear : unit -> unit
 val pyerr_fetch : pyobject * pyobject * pyobject -> pyobject * pyobject * 
pyobject
-val pyerr_restore : pyobject * pyobject * pyobject -> unit
 val pyerr_givenexceptionmatches : pyobject * pyobject -> int
 val pyerr_exceptionmatches : pyobject -> int
 val pyerr_normalizeexception : pyobject * pyobject * pyobject -> pyobject * 
pyobject * pyobject
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ocaml-pyml-20210226/pyml.opam 
new/ocaml-pyml-20210924/pyml.opam
--- old/ocaml-pyml-20210226/pyml.opam   2021-02-26 23:10:52.000000000 +0100
+++ new/ocaml-pyml-20210924/pyml.opam   2021-09-29 10:00:10.000000000 +0200
@@ -5,16 +5,15 @@
 bug-reports: "http://github.com/thierry-martinez/pyml/issues";
 license: "BSD-2-Clause"
 dev-repo: "git+https://github.com/thierry-martinez/pyml.git";
-build: [make "all" "pymltop" "pymlutop" {utop:installed} "PREFIX=%{prefix}%"]
-install: [make "install" "PREFIX=%{prefix}%"]
-run-test: [make "test"]
+build: ["dune" "build" "-p" name "-j" jobs "@install" "@runtest" {with-test} 
"@doc" {with-doc}]
 synopsis: "OCaml bindings for Python"
 description: "OCaml bindings for Python 2 and Python 3"
 depends: [
   "ocaml" {>= "3.12.1"}
+  "dune" {build & >= "2.8.0"}
   "ocamlfind" {build}
-  "stdcompat" {>= "13"}
+  "stdcompat" {>= "17"}
   "conf-python-3-dev" {with-test}
 ]
 depopts: ["utop"]
-version: "20210226"
\ No newline at end of file
+version: "20210924"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ocaml-pyml-20210226/pyml_arch.mli 
new/ocaml-pyml-20210924/pyml_arch.mli
--- old/ocaml-pyml-20210226/pyml_arch.mli       2021-02-26 23:10:52.000000000 
+0100
+++ new/ocaml-pyml-20210924/pyml_arch.mli       2021-09-29 10:00:10.000000000 
+0200
@@ -1,11 +1,25 @@
+(** List of possible names for libpython given major and minor versions.
+    On Linux, "libpython%d.%d.so"; on Mac OS X, "libpython%d.%d.dylib";
+    on Windows, "python%d%d.dll". There may be some variants to try,
+    like "libpython%d.%dm.so", so we return a list. *)
 val library_patterns: (int -> int -> string, unit, string) format list
 
+(** Suffix to add to library names returned by pkg-config (".so" on Linux,
+    ".dylib" on Mac OSX, we don't use pkg-config on Windows) *)
 val library_suffix: string
 
+(** Ensure that the executable has the ".exe" suffix on Windows, do nothing
+    on other platforms. *)
 val ensure_executable_suffix: string -> string
 
+(** The tool to search in PATH: "which" on Unix/Mac OS X; "where" on Windows. 
*)
 val which: string
 
+(** Convert a file descriptor index to a file descriptor usable in
+    OCaml.  It is the identity on Unix and Mac OS X, and the stdlib
+    "win_handle_fd" C stub on Windows. *)
 val fd_of_int: int -> Unix.file_descr
 
+(** Separator between paths in PATH environment variable. ":" on Unix/Mac OS X;
+    ";" on Windows. *)
 val path_separator: string
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ocaml-pyml-20210226/pyml_stubs.c 
new/ocaml-pyml-20210924/pyml_stubs.c
--- old/ocaml-pyml-20210226/pyml_stubs.c        2021-02-26 23:10:52.000000000 
+0100
+++ new/ocaml-pyml-20210924/pyml_stubs.c        2021-09-29 10:00:10.000000000 
+0200
@@ -200,6 +200,7 @@
 
 /* Wrapped by PyErr_Fetch_wrapper */
 static void (*Python_PyErr_Fetch)(PyObject **, PyObject **, PyObject **);
+static void (*Python_PyErr_Restore)(PyObject *, PyObject *, PyObject *);
 static void (*Python_PyErr_NormalizeException)
 (PyObject **, PyObject **, PyObject **);
 
@@ -222,6 +223,11 @@
 /* Internal use only */
 static void (*Python_PyMem_Free)(void *);
 
+/* Generate traceback objects. */
+static PyObject *(*Python_PyThreadState_Get)();
+static PyObject *(*Python_PyFrame_New)(PyObject*, PyObject*, PyObject*, 
PyObject*);
+static PyObject *(*Python_PyCode_NewEmpty)(const char*, const char*, int);
+
 static enum UCS { UCS_NONE, UCS2, UCS4 } ucs;
 
 /* Single instance of () */
@@ -698,6 +704,7 @@
     Python_PyObject_CallMethodObjArgs =
         resolve("PyObject_CallMethodObjArgs");
     Python_PyErr_Fetch = resolve("PyErr_Fetch");
+    Python_PyErr_Restore = resolve("PyErr_Restore");
     Python_PyErr_NormalizeException = resolve("PyErr_NormalizeException");
     Python_PyObject_AsCharBuffer = resolve_optional("PyObject_AsCharBuffer");
     Python_PyObject_AsReadBuffer = resolve_optional("PyObject_AsReadBuffer");
@@ -712,6 +719,9 @@
     }
     Python_PyLong_FromString = resolve("PyLong_FromString");
     Python_PyMem_Free = resolve("PyMem_Free");
+    Python_PyThreadState_Get = resolve("PyThreadState_Get");
+    Python_PyFrame_New = resolve("PyFrame_New");
+    Python_PyCode_NewEmpty = resolve("PyCode_NewEmpty");
     if (version_major >= 3) {
         Python__Py_wfopen = resolve_optional("_Py_wfopen"); /* Python >=3.10 */
         Python__Py_fopen = resolve_optional("_Py_fopen");
@@ -1143,6 +1153,26 @@
     CAMLreturn(result);
 }
 
+// PyErr_Restore steals the references.
+// https://docs.python.org/3/c-api/exceptions.html#c.PyErr_Restore
+// However the objects can be null, so we do not want to run Py_INCREF if
+// this is the case as this would trigger some segfaults.
+CAMLprim value
+PyErr_Restore_wrapper(value arg0_ocaml, value arg1_ocaml, value arg2_ocaml)
+{
+    CAMLparam3(arg0_ocaml, arg1_ocaml, arg2_ocaml);
+    pyml_assert_initialized();
+    PyObject *arg0 = pyml_unwrap(arg0_ocaml);
+    if (arg0) Py_INCREF(arg0);
+    PyObject *arg1 = pyml_unwrap(arg1_ocaml);
+    if (arg1) Py_INCREF(arg1);
+    PyObject *arg2 = pyml_unwrap(arg2_ocaml);
+    if (arg2) Py_INCREF(arg2);
+    Python_PyErr_Restore(arg0, arg1, arg2);
+    CAMLreturn(Val_unit);
+}
+
+
 CAMLprim value
 pyml_wrap_string_option(const char *s)
 {
@@ -1355,7 +1385,7 @@
     PyObject *c_api = pyml_unwrap(numpy_api_ocaml);
     void **PyArray_API = pyml_get_pyarray_api(c_api);
     PyObject *result = PyArray_API[2];
-    CAMLreturn(pyml_wrap(result, true));
+    CAMLreturn(pyml_wrap(result, false));
 }
 
 CAMLprim value
@@ -1370,6 +1400,9 @@
         (PyTypeObject *, int, npy_intp *, int, npy_intp *, void *, int, int,
          PyObject *) = PyArray_API[93];
     npy_intp length = Wosize_val(array_ocaml);
+    #ifndef ARCH_SIXTYFOUR
+      length /= 2;
+    #endif
     void *data = (double *) array_ocaml;
     PyTypeObject (*PyArray_SubType) =
         (PyTypeObject *) pyml_unwrap(array_type_ocaml);
@@ -1423,4 +1456,22 @@
     CAMLreturn(Val_int(result));
 }
 
+CAMLprim value
+pyml_pyframe_new(value filename_ocaml, value funcname_ocaml, value 
lineno_ocaml) {
+    CAMLparam3(filename_ocaml, funcname_ocaml, lineno_ocaml);
+    const char *filename = String_val(filename_ocaml);
+    const char *funcname = String_val(funcname_ocaml);
+    int lineno = Int_val(lineno_ocaml);
+    PyObject *code = Python_PyCode_NewEmpty(filename, funcname, lineno);
+    PyObject *globals = Python_PyDict_New();
+    PyObject *result = Python_PyFrame_New(
+        Python_PyThreadState_Get(),
+        code,
+        globals,
+        NULL);
+    Py_DECREF(code);
+    Py_DECREF(globals);
+    CAMLreturn(pyml_wrap(result, true));
+}
+
 #include "pyml_wrappers.inc"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ocaml-pyml-20210226/pyml_tests.ml 
new/ocaml-pyml-20210924/pyml_tests.ml
--- old/ocaml-pyml-20210226/pyml_tests.ml       2021-02-26 23:10:52.000000000 
+0100
+++ new/ocaml-pyml-20210924/pyml_tests.ml       2021-09-29 10:00:10.000000000 
+0200
@@ -164,6 +164,54 @@
 
 let () =
   Pyml_tests_common.add_test
+    ~title:"ocaml exception with traceback"
+    (fun () ->
+      let m = Py.Import.add_module "test" in
+      let traceback = [
+        {Py.Traceback.filename = "file1.ml"; function_name = "func1"; 
line_number = 1};
+        {Py.Traceback.filename = "file2.ml"; function_name = "func2"; 
line_number = 2}
+      ] in
+      let mywrap _ =
+        raise (Py.Err_with_traceback (Py.Err.Exception, "Great", traceback)) in
+      Py.Module.set_function m "mywrap" mywrap;
+      assert (Py.Run.simple_string "
+from test import mywrap
+import sys
+import traceback
+try:
+    mywrap()
+    raise Exception('No exception raised')
+except Exception as err:
+    if sys.version_info.major == 3 and sys.version_info.minor >= 7:
+        filenames = [f.filename for f in 
traceback.extract_tb(err.__traceback__)]
+        assert filenames == ['<string>', 'file2.ml', 'file1.ml']
+    assert str(err) == \"Great\"
+");
+      Pyml_tests_common.Passed
+    )
+
+let () =
+  Pyml_tests_common.add_test
+    ~title:"restore with null"
+    (fun () ->
+      try
+        let _ = Py.Run.eval ~start:Py.File "
+raise Exception('Great')
+" in
+        Pyml_tests_common.Failed "uncaught exception"
+      with Py.E (_, value) -> begin
+        assert (Py.Object.to_string value = "Great");
+        match Py.Err.fetched () with
+        | None -> Pyml_tests_common.Failed "unexpected none"
+        | Some (err, _args, _traceback) ->
+            (* Test that using [Py.Err.restore] on null works fine. *)
+            Py.Err.restore err Py.null Py.null;
+            Py.Err.clear ();
+            Pyml_tests_common.Passed
+    end)
+
+let () =
+  Pyml_tests_common.add_test
     ~title:"ocaml other exception"
     (fun () ->
       let m = Py.Import.add_module "test" in
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ocaml-pyml-20210226/pyops.ml 
new/ocaml-pyml-20210924/pyops.ml
--- old/ocaml-pyml-20210226/pyops.ml    2021-02-26 23:10:52.000000000 +0100
+++ new/ocaml-pyml-20210924/pyops.ml    1970-01-01 01:00:00.000000000 +0100
@@ -1,27 +0,0 @@
-let ( .@() ) = Py.Object.find_attr
-
-let ( .@$() ) = Py.Object.find_attr_string
-
-let ( .@()<- ) = Py.Object.set_attr
-
-let ( .@$()<- ) = Py.Object.set_attr_string
-
-let ( .![] ) = Py.Object.find
-
-let ( .!$[] ) = Py.Object.find_string
-
-let ( .![]<- ) = Py.Object.set_item
-
-let ( .!$[]<- ) = Py.Object.set_item_string
-
-let ( .%[] ) = Py.Dict.find
-
-let ( .%$[] ) = Py.Dict.find_string
-
-let ( .%[]<- ) = Py.Dict.set_item
-
-let ( .%$[]<- ) = Py.Dict.set_item_string
-
-let ( .&() ) = Py.Module.get_function
-
-let ( .&()<- ) = Py.Module.set_function
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ocaml-pyml-20210226/pyops.ml.new 
new/ocaml-pyml-20210924/pyops.ml.new
--- old/ocaml-pyml-20210226/pyops.ml.new        1970-01-01 01:00:00.000000000 
+0100
+++ new/ocaml-pyml-20210924/pyops.ml.new        2021-09-29 10:00:10.000000000 
+0200
@@ -0,0 +1,27 @@
+let ( .@() ) = Py.Object.find_attr
+
+let ( .@$() ) = Py.Object.find_attr_string
+
+let ( .@()<- ) = Py.Object.set_attr
+
+let ( .@$()<- ) = Py.Object.set_attr_string
+
+let ( .![] ) = Py.Object.find
+
+let ( .!$[] ) = Py.Object.find_string
+
+let ( .![]<- ) = Py.Object.set_item
+
+let ( .!$[]<- ) = Py.Object.set_item_string
+
+let ( .%[] ) = Py.Dict.find
+
+let ( .%$[] ) = Py.Dict.find_string
+
+let ( .%[]<- ) = Py.Dict.set_item
+
+let ( .%$[]<- ) = Py.Dict.set_item_string
+
+let ( .&() ) = Py.Module.get_function
+
+let ( .&()<- ) = Py.Module.set_function
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ocaml-pyml-20210226/pyops.mli 
new/ocaml-pyml-20210924/pyops.mli
--- old/ocaml-pyml-20210226/pyops.mli   2021-02-26 23:10:52.000000000 +0100
+++ new/ocaml-pyml-20210924/pyops.mli   1970-01-01 01:00:00.000000000 +0100
@@ -1,42 +0,0 @@
-val ( .@() ) : Py.Object.t -> Py.Object.t -> Py.Object.t
-(** Equivalent to {!Py.Object.find_attr}. *)
-
-val ( .@$() ) : Py.Object.t -> string -> Py.Object.t
-(** Equivalent to {!Py.Object.find_attr_string}. *)
-
-val ( .@()<- ) : Py.Object.t -> Py.Object.t -> Py.Object.t -> unit
-(** Equivalent to {!Py.Object.set_attr}. *)
-
-val ( .@$()<- ) : Py.Object.t -> string -> Py.Object.t -> unit
-(** Equivalent to {!Py.Object.set_attr_string}. *)
-
-val ( .![] ) : Py.Object.t -> Py.Object.t -> Py.Object.t
-(** Equivalent to {!Py.Object.find}. *)
-
-val ( .!$[] ) : Py.Object.t -> string -> Py.Object.t
-(** Equivalent to {!Py.Object.find_string}. *)
-
-val ( .![]<- ) : Py.Object.t -> Py.Object.t -> Py.Object.t -> unit
-(** Equivalent to {!Py.Object.set_item}. *)
-
-val ( .!$[]<- ) : Py.Object.t -> string -> Py.Object.t -> unit
-(** Equivalent to {!Py.Object.set_item_string}. *)
-
-val ( .%[] ) : Py.Object.t -> Py.Object.t -> Py.Object.t
-(** Equivalent to {!Py.Dict.find}. *)
-
-val ( .%$[] ) : Py.Object.t -> string -> Py.Object.t
-(** Equivalent to {!Py.Dict.find_string}. *)
-
-val ( .%[]<- ) : Py.Object.t -> Py.Object.t -> Py.Object.t -> unit
-(** Equivalent to {!Py.Dict.set_item}. *)
-
-val ( .%$[]<- ) : Py.Object.t -> string -> Py.Object.t -> unit
-(** Equivalent to {!Py.Dict.set_item_string}. *)
-
-val ( .&() ) : Py.Object.t -> string -> Py.Object.t array -> Py.Object.t
-(** Equivalent to {!Py.Module.get_function}. *)
-
-val ( .&()<- ) : Py.Object.t -> string -> (Py.Object.t array -> Py.Object.t)
-  -> unit
-(** Equivalent to {!Py.Module.set_function}. *)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ocaml-pyml-20210226/pyops.mli.new 
new/ocaml-pyml-20210924/pyops.mli.new
--- old/ocaml-pyml-20210226/pyops.mli.new       1970-01-01 01:00:00.000000000 
+0100
+++ new/ocaml-pyml-20210924/pyops.mli.new       2021-09-29 10:00:10.000000000 
+0200
@@ -0,0 +1,42 @@
+val ( .@() ) : Py.Object.t -> Py.Object.t -> Py.Object.t
+(** Equivalent to {!Py.Object.find_attr}. *)
+
+val ( .@$() ) : Py.Object.t -> string -> Py.Object.t
+(** Equivalent to {!Py.Object.find_attr_string}. *)
+
+val ( .@()<- ) : Py.Object.t -> Py.Object.t -> Py.Object.t -> unit
+(** Equivalent to {!Py.Object.set_attr}. *)
+
+val ( .@$()<- ) : Py.Object.t -> string -> Py.Object.t -> unit
+(** Equivalent to {!Py.Object.set_attr_string}. *)
+
+val ( .![] ) : Py.Object.t -> Py.Object.t -> Py.Object.t
+(** Equivalent to {!Py.Object.find}. *)
+
+val ( .!$[] ) : Py.Object.t -> string -> Py.Object.t
+(** Equivalent to {!Py.Object.find_string}. *)
+
+val ( .![]<- ) : Py.Object.t -> Py.Object.t -> Py.Object.t -> unit
+(** Equivalent to {!Py.Object.set_item}. *)
+
+val ( .!$[]<- ) : Py.Object.t -> string -> Py.Object.t -> unit
+(** Equivalent to {!Py.Object.set_item_string}. *)
+
+val ( .%[] ) : Py.Object.t -> Py.Object.t -> Py.Object.t
+(** Equivalent to {!Py.Dict.find}. *)
+
+val ( .%$[] ) : Py.Object.t -> string -> Py.Object.t
+(** Equivalent to {!Py.Dict.find_string}. *)
+
+val ( .%[]<- ) : Py.Object.t -> Py.Object.t -> Py.Object.t -> unit
+(** Equivalent to {!Py.Dict.set_item}. *)
+
+val ( .%$[]<- ) : Py.Object.t -> string -> Py.Object.t -> unit
+(** Equivalent to {!Py.Dict.set_item_string}. *)
+
+val ( .&() ) : Py.Object.t -> string -> Py.Object.t array -> Py.Object.t
+(** Equivalent to {!Py.Module.get_function}. *)
+
+val ( .&()<- ) : Py.Object.t -> string -> (Py.Object.t array -> Py.Object.t)
+  -> unit
+(** Equivalent to {!Py.Module.set_function}. *)

Reply via email to