summaryrefslogtreecommitdiff
path: root/numpy/distutils/system_info.py
diff options
context:
space:
mode:
authorNick R. Papior <nickpapior@gmail.com>2020-09-17 12:29:38 +0200
committerGitHub <noreply@github.com>2020-09-17 12:29:38 +0200
commit233c63a56974de22b846ac989cef1fabe45e7296 (patch)
tree1ec1cd1f4b606603fbf3035422070eb581857e7e /numpy/distutils/system_info.py
parent60a1e10c4593736b188b38e7d7c51aefb213af6a (diff)
downloadnumpy-233c63a56974de22b846ac989cef1fabe45e7296.tar.gz
BLD: enabled negation of library choices in NPY_*_ORDER (#17219)
BLD: enabled negation of library choices in NPY_*_ORDER When users build for a particular order it may be beneficial to disallow certain libraries. In particular a user may not care about which accelerated BLAS library is used, so long as the NetLIB or ATLAS library isn't used. This is now possible with: NPY_BLAS_ORDER='^blas,atlas' or NPY_BLAS_ORDER='!blas,atlas' Since we may envision more BLAS/LAPACK libraries to the pool, this will provide greater flexibility as they enter. A new (local) method is added in system_info.py which removes duplicate code and allows for easier usage across libraries.
Diffstat (limited to 'numpy/distutils/system_info.py')
-rw-r--r--numpy/distutils/system_info.py119
1 files changed, 85 insertions, 34 deletions
diff --git a/numpy/distutils/system_info.py b/numpy/distutils/system_info.py
index 19f7482f2..b4513825d 100644
--- a/numpy/distutils/system_info.py
+++ b/numpy/distutils/system_info.py
@@ -415,6 +415,83 @@ def get_standard_file(fname):
return filenames
+def _parse_env_order(base_order, env):
+ """ Parse an environment variable `env` by splitting with "," and only returning elements from `base_order`
+
+ This method will sequence the environment variable and check for their invidual elements in `base_order`.
+
+ The items in the environment variable may be negated via '^item' or '!itema,itemb'.
+ It must start with ^/! to negate all options.
+
+ Raises
+ ------
+ ValueError: for mixed negated and non-negated orders or multiple negated orders
+
+ Parameters
+ ----------
+ base_order : list of str
+ the base list of orders
+ env : str
+ the environment variable to be parsed, if none is found, `base_order` is returned
+
+ Returns
+ -------
+ allow_order : list of str
+ allowed orders in lower-case
+ unknown_order : list of str
+ for values not overlapping with `base_order`
+ """
+ order_str = os.environ.get(env, None)
+
+ # ensure all base-orders are lower-case (for easier comparison)
+ base_order = [order.lower() for order in base_order]
+ if order_str is None:
+ return base_order, []
+
+ neg = order_str.startswith('^') or order_str.startswith('!')
+ # Check format
+ order_str_l = list(order_str)
+ sum_neg = order_str_l.count('^') + order_str_l.count('!')
+ if neg:
+ if sum_neg > 1:
+ raise ValueError(f"Environment variable '{env}' may only contain a single (prefixed) negation: {order_str}")
+ # remove prefix
+ order_str = order_str[1:]
+ elif sum_neg > 0:
+ raise ValueError(f"Environment variable '{env}' may not mix negated an non-negated items: {order_str}")
+
+ # Split and lower case
+ orders = order_str.lower().split(',')
+
+ # to inform callee about non-overlapping elements
+ unknown_order = []
+
+ # if negated, we have to remove from the order
+ if neg:
+ allow_order = base_order.copy()
+
+ for order in orders:
+ if order not in base_order:
+ unknown_order.append(order)
+ continue
+
+ if order in allow_order:
+ allow_order.remove(order)
+
+ else:
+ allow_order = []
+
+ for order in orders:
+ if order not in base_order:
+ unknown_order.append(order)
+ continue
+
+ if order not in allow_order:
+ allow_order.append(order)
+
+ return allow_order, unknown_order
+
+
def get_info(name, notfound_action=0):
"""
notfound_action:
@@ -1766,24 +1843,11 @@ class lapack_opt_info(system_info):
return getattr(self, '_calc_info_{}'.format(name))()
def calc_info(self):
- user_order = os.environ.get(self.order_env_var_name, None)
- if user_order is None:
- lapack_order = self.lapack_order
- else:
- # the user has requested the order of the
- # check they are all in the available list, a COMMA SEPARATED list
- user_order = user_order.lower().split(',')
- non_existing = []
- lapack_order = []
- for order in user_order:
- if order in self.lapack_order:
- lapack_order.append(order)
- elif len(order) > 0:
- non_existing.append(order)
- if len(non_existing) > 0:
- raise ValueError("lapack_opt_info user defined "
- "LAPACK order has unacceptable "
- "values: {}".format(non_existing))
+ lapack_order, unknown_order = _parse_env_order(self.lapack_order, self.order_env_var_name)
+ if len(unknown_order) > 0:
+ raise ValueError("lapack_opt_info user defined "
+ "LAPACK order has unacceptable "
+ "values: {}".format(unknown_order))
for lapack in lapack_order:
if self._calc_info(lapack):
@@ -1911,22 +1975,9 @@ class blas_opt_info(system_info):
return getattr(self, '_calc_info_{}'.format(name))()
def calc_info(self):
- user_order = os.environ.get(self.order_env_var_name, None)
- if user_order is None:
- blas_order = self.blas_order
- else:
- # the user has requested the order of the
- # check they are all in the available list
- user_order = user_order.lower().split(',')
- non_existing = []
- blas_order = []
- for order in user_order:
- if order in self.blas_order:
- blas_order.append(order)
- elif len(order) > 0:
- non_existing.append(order)
- if len(non_existing) > 0:
- raise ValueError("blas_opt_info user defined BLAS order has unacceptable values: {}".format(non_existing))
+ blas_order, unknown_order = _parse_env_order(self.blas_order, self.order_env_var_name)
+ if len(unknown_order) > 0:
+ raise ValueError("blas_opt_info user defined BLAS order has unacceptable values: {}".format(unknown_order))
for blas in blas_order:
if self._calc_info(blas):