Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-threadpoolctl for 
openSUSE:Factory checked in at 2022-07-26 19:42:04
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-threadpoolctl (Old)
 and      /work/SRC/openSUSE:Factory/.python-threadpoolctl.new.1533 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-threadpoolctl"

Tue Jul 26 19:42:04 2022 rev:5 rq:990867 version:3.1.0

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-threadpoolctl/python-threadpoolctl.changes    
    2021-10-20 20:24:24.145382450 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-threadpoolctl.new.1533/python-threadpoolctl.changes
      2022-07-26 19:42:06.977204832 +0200
@@ -1,0 +2,12 @@
+Sun Jul 24 08:40:55 UTC 2022 - Dirk M??ller <[email protected]>
+
+- update to 3.1.0:
+  * Fixed a detection issue of the BLAS libraires packaged by conda-forge on 
Windows.
+    https://github.com/joblib/threadpoolctl/pull/112
+  * `threadpool_limits` and `ThreadpoolController.limit` now accept the string
+    "sequential_blas_under_openmp" for the `limits` parameter. It should only 
be used for
+    the specific case when one wants to have sequential BLAS calls within an 
OpenMP
+    parallel region. It takes into account the unexpected behavior of OpenBLAS 
with the
+    OpenMP threading layer.
+
+-------------------------------------------------------------------

Old:
----
  threadpoolctl-3.0.0.tar.gz

New:
----
  threadpoolctl-3.1.0.tar.gz

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

Other differences:
------------------
++++++ python-threadpoolctl.spec ++++++
--- /var/tmp/diff_new_pack.l9i1ed/_old  2022-07-26 19:42:07.473128199 +0200
+++ /var/tmp/diff_new_pack.l9i1ed/_new  2022-07-26 19:42:07.481126963 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-threadpoolctl
 #
-# 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
@@ -19,7 +19,7 @@
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %define skip_python2 1
 Name:           python-threadpoolctl
-Version:        3.0.0
+Version:        3.1.0
 Release:        0
 Summary:        Thread-pool Controls
 License:        BSD-3-Clause
@@ -27,6 +27,9 @@
 URL:            https://github.com/joblib/threadpoolctl
 Source:         
https://files.pythonhosted.org/packages/source/t/threadpoolctl/threadpoolctl-%{version}.tar.gz
 BuildRequires:  %{python_module devel}
+BuildRequires:  %{python_module flit-core}
+BuildRequires:  %{python_module pep517}
+BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module pytest}
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  fdupes
@@ -43,10 +46,10 @@
 %setup -q -n threadpoolctl-%{version}
 
 %build
-%python_build
+%pyproject_wheel
 
 %install
-%python_install
+%pyproject_install
 %python_expand %fdupes %{buildroot}%{$python_sitelib}
 
 %check

++++++ threadpoolctl-3.0.0.tar.gz -> threadpoolctl-3.1.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/threadpoolctl-3.0.0/.azure_pipeline.yml 
new/threadpoolctl-3.1.0/.azure_pipeline.yml
--- old/threadpoolctl-3.0.0/.azure_pipeline.yml 2021-09-24 10:58:15.330052900 
+0200
+++ new/threadpoolctl-3.1.0/.azure_pipeline.yml 2022-01-31 16:08:24.277708800 
+0100
@@ -6,6 +6,14 @@
   JUNITXML: 'test-data.xml'
   CODECOV_TOKEN: 'cee0e505-c12e-4139-aa43-621fb16a2347'
 
+schedules:
+- cron: "0 1 * * *"  # 1am UTC
+  displayName: Run nightly build
+  branches:
+    include:
+    - master
+  always: true
+
 stages:
 - stage:
   jobs:
@@ -13,11 +21,16 @@
   - template: continuous_integration/windows.yml
     parameters:
       name: Windows
-      vmImage: vs2017-win2016
+      vmImage: windows-latest
       matrix:
-        pylatest_conda:
+        pylatest_conda_forge_mkl:
           VERSION_PYTHON: '*'
-          PACKAGER: 'conda'
+          PACKAGER: 'conda-forge'
+          BLAS: 'mkl'
+        py39_conda_forge_openblas:
+          VERSION_PYTHON: '3.9'
+          PACKAGER: 'conda-forge'
+          BLAS: 'openblas'
         py37_conda:
           VERSION_PYTHON: '3.7'
           PACKAGER: 'conda'
@@ -76,11 +89,12 @@
           VERSION_PYTHON: '3.8'
           CC_OUTER_LOOP: 'gcc'
           CC_INNER_LOOP: 'clang-10'
-        # Linux environment with numpy from conda-forge channel
+        # Linux environment with numpy from conda-forge channel and 
openblas-openmp
         pylatest_conda_forge:
           PACKAGER: 'conda-forge'
           VERSION_PYTHON: '*'
           BLAS: 'openblas'
+          OPENBLAS_THREADING_LAYER: 'openmp'
           CC_OUTER_LOOP: 'gcc'
           CC_INNER_LOOP: 'gcc'
           LINT: 'true'
@@ -123,7 +137,7 @@
   - template: continuous_integration/posix.yml
     parameters:
       name: macOS
-      vmImage: macOS-10.14
+      vmImage: macOS-10.15
       matrix:
         # MacOS environment with OpenMP installed through homebrew
         py36_conda_homebrew_libomp:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/threadpoolctl-3.0.0/CHANGES.md 
new/threadpoolctl-3.1.0/CHANGES.md
--- old/threadpoolctl-3.0.0/CHANGES.md  2021-10-01 13:56:45.369609800 +0200
+++ new/threadpoolctl-3.1.0/CHANGES.md  2022-01-31 17:25:14.640525300 +0100
@@ -1,3 +1,16 @@
+3.1.0 (2022-01-31)
+==================
+
+- Fixed a detection issue of the BLAS libraires packaged by conda-forge on 
Windows.
+  https://github.com/joblib/threadpoolctl/pull/112
+
+- `threadpool_limits` and `ThreadpoolController.limit` now accept the string
+  "sequential_blas_under_openmp" for the `limits` parameter. It should only be 
used for
+  the specific case when one wants to have sequential BLAS calls within an 
OpenMP
+  parallel region. It takes into account the unexpected behavior of OpenBLAS 
with the
+  OpenMP threading layer.
+  https://github.com/joblib/threadpoolctl/pull/114
+
 3.0.0 (2021-10-01)
 ==================
 
@@ -50,7 +63,7 @@
 2.0.0 (2019-12-05)
 ==================
 
-- Expose MKL, BLIS and OpenBLAS threading layer in informations displayed by
+- Expose MKL, BLIS and OpenBLAS threading layer in information displayed by
   `threadpool_info`. This information is referenced in the `threading_layer`
   field.
   https://github.com/joblib/threadpoolctl/pull/48
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/threadpoolctl-3.0.0/PKG-INFO 
new/threadpoolctl-3.1.0/PKG-INFO
--- old/threadpoolctl-3.0.0/PKG-INFO    1970-01-01 01:00:00.000000000 +0100
+++ new/threadpoolctl-3.1.0/PKG-INFO    1970-01-01 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: threadpoolctl
-Version: 3.0.0
+Version: 3.1.0
 Summary: threadpoolctl
 Home-page: https://github.com/joblib/threadpoolctl
 License: BSD-3-Clause
@@ -177,7 +177,7 @@
 
 The threadpools can also be controlled via the object oriented API, which is 
especially
 useful to avoid searching through all the loaded shared libraries each time. 
It will
-however not act on libraries loaded after the instanciation of the
+however not act on libraries loaded after the instantiation of the
 `ThreadpoolController`:
 
 ```python
@@ -211,6 +211,13 @@
 ...
 ```
 
+### Sequential BLAS within OpenMP parallel region
+
+When one wants to have sequential BLAS calls within an OpenMP parallel region, 
it's
+safer to set `limits="sequential_blas_under_openmp"` since setting `limits=1` 
and `user_api="blas"` might not lead to the expected behavior in some 
configurations
+(e.g. OpenBLAS with the OpenMP threading layer
+https://github.com/xianyi/OpenBLAS/issues/2985).
+
 ### Known Limitations
 
 - `threadpool_limits` can fail to limit the number of inner threads when 
nesting
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/threadpoolctl-3.0.0/README.md 
new/threadpoolctl-3.1.0/README.md
--- old/threadpoolctl-3.0.0/README.md   2021-10-01 10:32:57.836148700 +0200
+++ new/threadpoolctl-3.1.0/README.md   2022-01-31 16:08:24.277708800 +0100
@@ -158,7 +158,7 @@
 
 The threadpools can also be controlled via the object oriented API, which is 
especially
 useful to avoid searching through all the loaded shared libraries each time. 
It will
-however not act on libraries loaded after the instanciation of the
+however not act on libraries loaded after the instantiation of the
 `ThreadpoolController`:
 
 ```python
@@ -192,6 +192,13 @@
 ...
 ```
 
+### Sequential BLAS within OpenMP parallel region
+
+When one wants to have sequential BLAS calls within an OpenMP parallel region, 
it's
+safer to set `limits="sequential_blas_under_openmp"` since setting `limits=1` 
and `user_api="blas"` might not lead to the expected behavior in some 
configurations
+(e.g. OpenBLAS with the OpenMP threading layer
+https://github.com/xianyi/OpenBLAS/issues/2985).
+
 ### Known Limitations
 
 - `threadpool_limits` can fail to limit the number of inner threads when 
nesting
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/threadpoolctl-3.0.0/continuous_integration/install.cmd 
new/threadpoolctl-3.1.0/continuous_integration/install.cmd
--- old/threadpoolctl-3.0.0/continuous_integration/install.cmd  2021-09-15 
15:26:21.489843100 +0200
+++ new/threadpoolctl-3.1.0/continuous_integration/install.cmd  2022-01-20 
18:05:26.048133900 +0100
@@ -18,8 +18,11 @@
 pip --version
 
 @rem Install dependencies with either conda or pip.
-if "%PACKAGER%" == "conda" (%CONDA_INSTALL% numpy scipy pytest cython)
-if "%PACKAGER%" == "pip" (%PIP_INSTALL% numpy scipy pytest cython)
+set TO_INSTALL=numpy scipy cython pytest
+
+if "%PACKAGER%" == "conda" (%CONDA_INSTALL% %TO_INSTALL%)
+if "%PACKAGER%" == "conda-forge" (%CONDA_INSTALL% -c conda-forge %TO_INSTALL% 
blas[build=%BLAS%])
+if "%PACKAGER%" == "pip" (%PIP_INSTALL% %TO_INSTALL%)
 
 @rem Install extra developer dependencies
 pip install -q -r dev-requirements.txt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/threadpoolctl-3.0.0/continuous_integration/install.sh 
new/threadpoolctl-3.1.0/continuous_integration/install.sh
--- old/threadpoolctl-3.0.0/continuous_integration/install.sh   2021-09-24 
13:00:01.009218500 +0200
+++ new/threadpoolctl-3.1.0/continuous_integration/install.sh   2022-01-31 
16:08:24.277708800 +0100
@@ -50,6 +50,9 @@
     conda config --prepend channels conda-forge
     conda config --set channel_priority strict
     TO_INSTALL="python=$VERSION_PYTHON numpy scipy blas[build=$BLAS]"
+    if [[ "$BLAS" == "openblas" && "$OPENBLAS_THREADING_LAYER" == "openmp" ]]; 
then
+        TO_INSTALL="$TO_INSTALL libopenblas=*=*openmp*"
+    fi
     make_conda $TO_INSTALL
 
 elif [[ "$PACKAGER" == "pip" ]]; then
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/threadpoolctl-3.0.0/continuous_integration/install_with_blis.sh 
new/threadpoolctl-3.1.0/continuous_integration/install_with_blis.sh
--- old/threadpoolctl-3.0.0/continuous_integration/install_with_blis.sh 
2021-09-24 13:00:01.009218500 +0200
+++ new/threadpoolctl-3.1.0/continuous_integration/install_with_blis.sh 
2022-01-20 18:05:26.048133900 +0100
@@ -35,6 +35,7 @@
 # build & install numpy
 git clone https://github.com/numpy/numpy.git
 pushd numpy
+git submodule update --init
 echo "[blis]
 libraries = blis
 library_dirs = $ABS_PATH/BLIS_install/lib
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/threadpoolctl-3.0.0/continuous_integration/test_script.cmd 
new/threadpoolctl-3.1.0/continuous_integration/test_script.cmd
--- old/threadpoolctl-3.0.0/continuous_integration/test_script.cmd      
2021-09-15 15:26:21.493843300 +0200
+++ new/threadpoolctl-3.1.0/continuous_integration/test_script.cmd      
2022-01-20 18:05:26.048133900 +0100
@@ -2,6 +2,6 @@
 
 # Use the CLI to display the effective runtime environment prior to
 # launching the tests:
-python -m threadpoolctl -i numpy scipy.linalg tests._openmp_test_helper
+python -m threadpoolctl -i numpy scipy.linalg 
tests._openmp_test_helper.openmp_helpers_inner
 
 pytest -vlrxXs --junitxml=%JUNITXML% --cov=threadpoolctl
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/threadpoolctl-3.0.0/continuous_integration/test_script.sh 
new/threadpoolctl-3.1.0/continuous_integration/test_script.sh
--- old/threadpoolctl-3.0.0/continuous_integration/test_script.sh       
2021-09-15 15:26:21.493843300 +0200
+++ new/threadpoolctl-3.1.0/continuous_integration/test_script.sh       
2022-01-20 18:05:26.048133900 +0100
@@ -15,6 +15,6 @@
 
 # Use the CLI to display the effective runtime environment prior to
 # launching the tests:
-python -m threadpoolctl -i numpy scipy.linalg tests._openmp_test_helper
+python -m threadpoolctl -i numpy scipy.linalg 
tests._openmp_test_helper.openmp_helpers_inner
 
 pytest -vlrxXs -W error -k "$TESTS" --junitxml=$JUNITXML --cov=threadpoolctl
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/threadpoolctl-3.0.0/pyproject.toml 
new/threadpoolctl-3.1.0/pyproject.toml
--- old/threadpoolctl-3.0.0/pyproject.toml      2021-09-24 10:58:15.330052900 
+0200
+++ new/threadpoolctl-3.1.0/pyproject.toml      2022-01-31 16:08:24.277708800 
+0100
@@ -1,6 +1,6 @@
 [build-system]
-requires = ["flit"]
-build-backend = "flit.buildapi"
+requires = ["flit_core"]
+build-backend = "flit_core.buildapi"
 
 [tool.flit.metadata]
 module = "threadpoolctl"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/threadpoolctl-3.0.0/setup.py 
new/threadpoolctl-3.1.0/setup.py
--- old/threadpoolctl-3.0.0/setup.py    1970-01-01 01:00:00.000000000 +0100
+++ new/threadpoolctl-3.1.0/setup.py    1970-01-01 01:00:00.000000000 +0100
@@ -1,15 +0,0 @@
-#!/usr/bin/env python
-# setup.py generated by flit for tools that don't yet use PEP 517
-
-from distutils.core import setup
-
-
-setup(name='threadpoolctl',
-      version='3.0.0',
-      description='threadpoolctl',
-      author='Thomas Moreau',
-      author_email='[email protected]',
-      url='https://github.com/joblib/threadpoolctl',
-      py_modules=['threadpoolctl'],
-      python_requires='>=3.6',
-     )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/threadpoolctl-3.0.0/tests/_openmp_test_helper/openmp_helpers_inner.pyx 
new/threadpoolctl-3.1.0/tests/_openmp_test_helper/openmp_helpers_inner.pyx
--- old/threadpoolctl-3.0.0/tests/_openmp_test_helper/openmp_helpers_inner.pyx  
2021-09-15 15:26:21.493843300 +0200
+++ new/threadpoolctl-3.1.0/tests/_openmp_test_helper/openmp_helpers_inner.pyx  
2021-12-31 17:52:30.808669800 +0100
@@ -22,7 +22,7 @@
     OpenMP runtime.
 
     This function is expected to run without the GIL and can be called
-    by an outer OpenMP / prange loop written in Cython in anoter file.
+    by an outer OpenMP / prange loop written in Cython in another file.
     """
     cdef long n_sum = 0
     cdef int i, num_threads
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/threadpoolctl-3.0.0/tests/test_threadpoolctl.py 
new/threadpoolctl-3.1.0/tests/test_threadpoolctl.py
--- old/threadpoolctl-3.0.0/tests/test_threadpoolctl.py 2021-10-01 
10:59:48.573305600 +0200
+++ new/threadpoolctl-3.1.0/tests/test_threadpoolctl.py 2022-01-31 
16:08:24.277708800 +0100
@@ -208,8 +208,42 @@
             for lib_controller in blas_controller.lib_controllers
         )
         # original_blas_controller contains only blas libraries so no opemp 
library
-        # should be impacted.
-        assert openmp_info == original_openmp_info
+        # should be impacted. This is not True for OpenBLAS with the OpenMP 
threading
+        # layer.
+        if not any(
+            lib_controller.internal_api == "openblas"
+            and lib_controller.threading_layer == "openmp"
+            for lib_controller in blas_controller.lib_controllers
+        ):
+            assert openmp_info == original_openmp_info
+
+
+def test_get_params_for_sequential_blas_under_openmp():
+    # Test for the behavior of get_params_for_sequential_blas_under_openmp.
+    controller = ThreadpoolController()
+    original_info = controller.info()
+
+    params = controller._get_params_for_sequential_blas_under_openmp()
+
+    if controller.select(
+        internal_api="openblas", threading_layer="openmp"
+    ).lib_controllers:
+        assert params["limits"] is None
+        assert params["user_api"] is None
+
+        with controller.limit(limits="sequential_blas_under_openmp"):
+            assert controller.info() == original_info
+
+    else:
+        assert params["limits"] == 1
+        assert params["user_api"] == "blas"
+
+        with controller.limit(limits="sequential_blas_under_openmp"):
+            assert all(
+                lib_info["num_threads"] == 1
+                for lib_info in controller.info()
+                if lib_info["user_api"] == "blas"
+            )
 
 
 def test_nested_limits():
@@ -245,7 +279,7 @@
         threadpool_limits(limits=1, user_api="wrong")
 
     with pytest.raises(
-        TypeError, match="limits must either be an int, a list or a dict"
+        TypeError, match="limits must either be an int, a list, a dict, or"
     ):
         threadpool_limits(limits=(1, 2, 3))
 
@@ -552,8 +586,11 @@
         # XXX: add more as needed by CI or developer laptops
         "armv8",
         "Haswell",
+        "Prescott",  # see: https://github.com/xianyi/OpenBLAS/pull/3485
         "SkylakeX",
         "Sandybridge",
+        "VORTEX",
+        "Zen",
     )
     expected_blis_architectures = (
         # XXX: add more as needed by CI or developer laptops
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/threadpoolctl-3.0.0/threadpoolctl.py 
new/threadpoolctl-3.1.0/threadpoolctl.py
--- old/threadpoolctl-3.0.0/threadpoolctl.py    2021-10-01 13:56:45.369609800 
+0200
+++ new/threadpoolctl-3.1.0/threadpoolctl.py    2022-01-31 17:25:14.640525300 
+0100
@@ -7,7 +7,7 @@
 # License: BSD 3-Clause
 
 # The code to introspect dynamically loaded libraries on POSIX systems is
-# adapted from code by Intel developper @anton-malakhov available at
+# adapted from code by Intel developer @anton-malakhov available at
 # https://github.com/IntelPython/smp (Copyright (c) 2017, Intel Corporation)
 # and also published under the BSD 3-Clause license
 import os
@@ -21,7 +21,7 @@
 from functools import lru_cache
 from contextlib import ContextDecorator
 
-__version__ = "3.0.0"
+__version__ = "3.1.0"
 __all__ = ["threadpool_limits", "threadpool_info", "ThreadpoolController"]
 
 
@@ -61,9 +61,11 @@
 
 
 # List of the supported libraries. The items are indexed by the name of the
-# class to instanciate to create the library controller objects. The items hold
+# class to instantiate to create the library controller objects. The items hold
 # the possible prefixes of loaded shared objects, the name of the internal_api
-# to call and the name of the user_api.
+# to call, the name of the user_api and potentially some symbols that the 
library is
+# expected to have (this is necessary to distinguish between the blas 
implementations
+# when they are all renamed "libblas.dll" on conda-forge on windows).
 _SUPPORTED_LIBRARIES = {
     "OpenMPController": {
         "user_api": "openmp",
@@ -73,28 +75,33 @@
     "OpenBLASController": {
         "user_api": "blas",
         "internal_api": "openblas",
-        "filename_prefixes": ("libopenblas",),
+        "filename_prefixes": ("libopenblas", "libblas"),
+        "check_symbols": ("openblas_get_num_threads", 
"openblas_get_num_threads64_"),
     },
     "MKLController": {
         "user_api": "blas",
         "internal_api": "mkl",
-        "filename_prefixes": ("libmkl_rt", "mkl_rt"),
+        "filename_prefixes": ("libmkl_rt", "mkl_rt", "libblas"),
+        "check_symbols": ("MKL_Get_Max_Threads",),
     },
     "BLISController": {
         "user_api": "blas",
         "internal_api": "blis",
-        "filename_prefixes": ("libblis",),
+        "filename_prefixes": ("libblis", "libblas"),
+        "check_symbols": ("bli_thread_get_num_threads",),
     },
 }
 
 # Helpers for the doc and test names
 _ALL_USER_APIS = list(set(lib["user_api"] for lib in 
_SUPPORTED_LIBRARIES.values()))
 _ALL_INTERNAL_APIS = [lib["internal_api"] for lib in 
_SUPPORTED_LIBRARIES.values()]
-_ALL_PREFIXES = [
-    prefix
-    for lib in _SUPPORTED_LIBRARIES.values()
-    for prefix in lib["filename_prefixes"]
-]
+_ALL_PREFIXES = list(
+    set(
+        prefix
+        for lib in _SUPPORTED_LIBRARIES.values()
+        for prefix in lib["filename_prefixes"]
+    )
+)
 _ALL_BLAS_LIBRARIES = [
     lib["internal_api"]
     for lib in _SUPPORTED_LIBRARIES.values()
@@ -151,10 +158,10 @@
     """
 
     def __init__(self, controller, *, limits=None, user_api=None):
+        self._controller = controller
         self._limits, self._user_api, self._prefixes = self._check_params(
             limits, user_api
         )
-        self._controller = controller
         self._original_info = self._controller.info()
         self._set_threadpool_limits()
 
@@ -219,6 +226,13 @@
 
     def _check_params(self, limits, user_api):
         """Suitable values for the _limits, _user_api and _prefixes 
attributes"""
+
+        if isinstance(limits, str) and limits == 
"sequential_blas_under_openmp":
+            (
+                limits,
+                user_api,
+            ) = 
self._controller._get_params_for_sequential_blas_under_openmp().values()
+
         if limits is None or isinstance(limits, int):
             if user_api is None:
                 user_api = _ALL_USER_APIS
@@ -250,8 +264,8 @@
 
             if not isinstance(limits, dict):
                 raise TypeError(
-                    "limits must either be an int, a list or a "
-                    f"dict. Got {type(limits)} instead"
+                    "limits must either be an int, a list, a dict, or "
+                    f"'sequential_blas_under_openmp'. Got {type(limits)} 
instead"
                 )
 
             # With a dictionary, can set both specific limit for given
@@ -326,7 +340,7 @@
 
     Parameters
     ----------
-    limits : int, dict or None (default=None)
+    limits : int, dict, 'sequential_blas_under_openmp' or None (default=None)
         The maximal number of threads that can be used in thread pools
 
         - If int, sets the maximum number of threads to `limits` for each
@@ -336,6 +350,11 @@
           custom maximum number of threads for each `key` which can be either a
           `user_api` or a `prefix` for a specific library.
 
+        - If 'sequential_blas_under_openmp', it will chose the appropriate 
`limits`
+          and `user_api` parameters for the specific use case of sequential 
BLAS
+          calls within an OpenMP parallel region. The `user_api` parameter is
+          ignored.
+
         - If None, this function does not do anything.
 
     user_api : {USER_APIS} or None (default=None)
@@ -421,6 +440,18 @@
 
         return ThreadpoolController._from_controllers(lib_controllers)
 
+    def _get_params_for_sequential_blas_under_openmp(self):
+        """Return appropriate params to use for a sequential BLAS call in an 
OpenMP loop
+
+        This function takes into account the unexpected behavior of OpenBLAS 
with the
+        OpenMP threading layer.
+        """
+        if self.select(
+            internal_api="openblas", threading_layer="openmp"
+        ).lib_controllers:
+            return {"limits": None, "user_api": None}
+        return {"limits": 1, "user_api": "blas"}
+
     @_format_docstring(
         USER_APIS=", ".join('"{}"'.format(api) for api in _ALL_USER_APIS),
         BLAS_LIBS=", ".join(_ALL_BLAS_LIBRARIES),
@@ -444,7 +475,7 @@
 
         Parameters
         ----------
-        limits : int, dict or None (default=None)
+        limits : int, dict, 'sequential_blas_under_openmp' or None 
(default=None)
             The maximal number of threads that can be used in thread pools
 
             - If int, sets the maximum number of threads to `limits` for each
@@ -454,6 +485,11 @@
               custom maximum number of threads for each `key` which can be 
either a
               `user_api` or a `prefix` for a specific library.
 
+            - If 'sequential_blas_under_openmp', it will chose the appropriate 
`limits`
+              and `user_api` parameters for the specific use case of 
sequential BLAS
+              calls within an OpenMP parallel region. The `user_api` parameter 
is
+              ignored.
+
             - If None, this function does not do anything.
 
         user_api : {USER_APIS} or None (default=None)
@@ -526,7 +562,7 @@
         """Loop through loaded libraries and return binders on supported ones
 
         This function is expected to work on POSIX system only.
-        This code is adapted from code by Intel developper @anton-malakhov
+        This code is adapted from code by Intel developer @anton-malakhov
         available at https://github.com/IntelPython/smp
 
         Copyright (c) 2017, Intel Corporation published under the BSD 3-Clause
@@ -660,6 +696,26 @@
             if prefix is None:
                 continue
 
+            # workaround for BLAS libraries packaged by conda-forge on 
windows, which
+            # are all renamed "libblas.dll". We thus have to check to which 
BLAS
+            # implementation it actually corresponds looking for implementation
+            # specific symbols.
+            if prefix == "libblas":
+                if filename.endswith(".dll"):
+                    libblas = ctypes.CDLL(filepath, _RTLD_NOLOAD)
+                    if not any(
+                        hasattr(libblas, func)
+                        for func in candidate_lib["check_symbols"]
+                    ):
+                        continue
+                else:
+                    # We ignore libblas on other platforms than windows 
because there
+                    # might be a libblas dso comming with openblas for 
instance that
+                    # can't be used to instantiate a pertinent LibController 
(many
+                    # symbols are missing) and would create confusion by 
making a
+                    # duplicate entry in threadpool_info.
+                    continue
+
             # filename matches a prefix. Create and store the library
             # controller.
             user_api = candidate_lib["user_api"]

Reply via email to