Skip to content
Snippets Groups Projects
Unverified Commit f13f786a authored by Robin De Schepper's avatar Robin De Schepper Committed by GitHub
Browse files

Fixed MRO and code duplication in `setup.py` (#1672)

The duplication arose from slightly more complicated composition than usual but could be resolved by proper MRO, it took me a few passes from its original form as well before I figured out the situation is not as complicated as it seems.

`super()` is equal to `super(cls, self)` where `cls` is obtained from the current function's class scope. If arg 2  is an object it will start an MRO search of the object, but skipping classes before the 1st arg type is encountered. In our case with the following base classes: `(_command_template, base_command_class)` this means we can define our base logic in `_command_template` and use `super()` calls there to traverse the MRO in `(base_command_class,)`, so by simply defining `class install_command(_command_template, install)` and `bdist_wheel_command(_command_template, bdist_wheel)` our MRO issue is solved and the duplication removed.
parent c34b7c96
No related branches found
No related tags found
No related merge requests found
......@@ -62,15 +62,36 @@ def check_cmake():
except OSError:
return False
# Extend the command line options available to the install phase.
# These arguments must come after `install` on the command line, e.g.:
# python3 setup.py install --mpi --arch=skylake
# pip3 install --install-option '--mpi' --install-option '--arch=skylake' .
class install_command(install):
user_options = install.user_options + user_options_
class _command_template:
"""
Override a setuptools-like command to augment the command line options.
Needs to appear before the command class in the class's argument list for
correct MRO.
Examples
--------
.. code-block: python
class install_command(_command_template, install):
pass
class complex_command(_command_template, mixin1, install):
def initialize_options(self):
# Both here and in `mixin1`, a `super` call is required
super().initialize_options()
# ...
"""
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
cls.user_options = super().user_options + user_options_
def initialize_options(self):
install.initialize_options(self)
super().initialize_options()
self.mpi = None
self.gpu = None
self.arch = None
......@@ -79,7 +100,7 @@ class install_command(install):
self.sysdeps = None
def finalize_options(self):
install.finalize_options(self)
super().finalize_options()
def run(self):
# The options are stored in global variables:
......@@ -98,47 +119,22 @@ class install_command(install):
# By default use bundled libs.
opt['bundled'] = self.sysdeps is None
install.run(self)
super().run()
class install_command(_command_template, install):
pass
if WHEEL_INSTALLED:
class bdist_wheel_command(bdist_wheel):
user_options = bdist_wheel.user_options + user_options_
def initialize_options(self):
bdist_wheel.initialize_options(self)
self.mpi = None
self.gpu = None
self.arch = None
self.vec = None
self.neuroml = None
self.sysdeps = None
def finalize_options(self):
bdist_wheel.finalize_options(self)
def run(self):
# The options are stored in global variables:
opt = cl_opt()
# mpi : build with MPI support (boolean).
opt['mpi'] = self.mpi is not None
# gpu : compile for AMD/NVIDIA GPUs and choose compiler (string).
opt['gpu'] = "none" if self.gpu is None else self.gpu
# vec : generate SIMD vectorized kernels for CPU micro-architecture (boolean).
opt['vec'] = self.vec is not None
# arch : target CPU micro-architecture (string).
opt['arch'] = 'none' if self.arch is None else self.arch
# neuroml : compile with neuroml support for morphologies.
opt['neuroml'] = self.neuroml is not None
# bundled : use bundled/git-submoduled 3rd party libraries.
# By default use bundled libs.
opt['bundled'] = self.sysdeps is None
bdist_wheel.run(self)
class bdist_wheel_command(_command_template, bdist_wheel):
pass
class cmake_extension(Extension):
def __init__(self, name):
Extension.__init__(self, name, sources=[])
class cmake_build(build_ext):
def run(self):
if not check_cmake():
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment