Skip to content

Enhancement Proposal: Make Python Spack Installs Ignore User Configuration#950

Merged
tgamblin merged 3 commits intospack:developfrom
xjrc:packages/python
Jul 22, 2016
Merged

Enhancement Proposal: Make Python Spack Installs Ignore User Configuration#950
tgamblin merged 3 commits intospack:developfrom
xjrc:packages/python

Conversation

@xjrc
Copy link
Copy Markdown
Member

@xjrc xjrc commented May 13, 2016

Python's build system provides a lot of room for granular levels of customization through the use and application of user, system, and distribution configuration files. While these files are very useful for customizing Python builds, they tend to negatively impact Spack's installation processes for Python and Python extensions by adding unwanted configuration options (which can alter the destinations of Spack's installs). In order to allow Spack installations of Python libraries to coexist with these files, a solution must be implemented that allows Spack's install scripts to ignore these configuration files and all external install scripts that use Spack's Python to acknowledge them.

I've outlined a few potential solutions to this problem below:

  • Add --no-user-cfg to Each Python Extension's Install Command: This solution will require changing the most files, but will necessitate zero additional changes to Spack's infrastructure or the Python package. This solution is potentially undesirable because it requires authors for Python extension packages to acknowledge and properly account for the the fact that user configuration needs to be ignored.
  • Add python_setup Function to Python Extensions: This solution involves adding new function to Python extension modules that sets up extension files while ignoring user configurations (i.e. something that invokes python setup.py --no-user-cfg [setup-instruction] [arguments]). This solution avoids the majority of the acknowledgement problems of the previous solution (authors will still have to remember to call python_setup instead of python('setup.py', 'install')), but still requires that all the Python extension install scripts be updated.
  • Pre-Install setup.cfg into Each Python Extension's Install Directory: This solution involves taking advantage of Python's hierarchy of configuration files to override user and system options. No Python extension packages need to be modified in this solution, but the Python package will need to install a file into each extension package's install directory (probably similar to the Package.setup_dependent_package function but occurring after the staging process for the dependent begins). Additionally, due to a bug in Python's configuration capture functionality, this method will require a nontrivial patch to be applied to the Python distutils source code (which is probably not portable to versions of Python outside of 2.7).

If anyone has any thoughts about the methods that I've outlined or has any alternative solutions (especially frequent users of the Python package like @alalazo, @citibeth, @glennpj, @tgamblin), please let me know! Given that each solution will require some fairly significant changes to Spack's Python packages, I'd like some input before I start writing anything major. Thanks!

@tgamblin
Copy link
Copy Markdown
Member

tgamblin commented May 13, 2016

@xjrc: RE: solution 1, we could do what we do for configure, make, and cmake -- we add a special Executable object to the package environment and put some default args on it. In this case we could add a module-scope setup_py executable that includes --no-user-cfg. That would be simpler than the patching required on the second two options, and users who tweak their python setup beyond the defaults would need to know to add the --no-user-cfg option themselves.

The cmake callable object is similar -- it adds things like -DCMAKE_BUILD_TYPE=RelWithDebInfo and -DCMAKE_INSTALL_PREFIX=$prefix.

what do you think?

@xjrc
Copy link
Copy Markdown
Member Author

xjrc commented May 13, 2016

@tgamblin: This sounds perfectly reasonable to me. The only concern that I have is that this will require updating all of the existing Python extension packages so that they use setup_py(*args) instead of python('setup.py', *args) in order to be unaffected by user configuration. This isn't hard to do with sed, but it will mean that a lot of packages will be changed with this update. Is that okay?

@tgamblin
Copy link
Copy Markdown
Member

@xjrc: this would not be such a bad thing. We'd need to make sure the PR works for all the users, but we can announce this at the telcons and on the mailing list and let them try it out before we throw it in the mainline. I think that should be sufficient.

@xjrc
Copy link
Copy Markdown
Member Author

xjrc commented May 13, 2016

@tgamblin: Okay, that sounds good to me; I'll get to work on writing this up. Thanks for your help!

@citibeth
Copy link
Copy Markdown
Member

Please look at PR #543, which adds some functionality to CMake-based projects. A similar pattern might be useful for Python-based projects.

in particular, PR #543 creates a subclass of Package called CMakePackage. Package authors using CMakePackage don't implement install(), instead they implement configur_args(), which is responsible only for returning package-specific CMake configuration args. CMakePackage has its own install() method that calls configure_args(). A similar pattern for subclass PythonPackage would allow PythonPackage to do all sorts of stuff without forcing each package instance to do anything specific, or even call some specific magic function.

    def configure_args(self):
        spec = self.spec
        return [
            '-DUSE_EVERYTRACE=%s' % ('YES' if '+everytrace' in spec else 'NO'),
            '-DBUILD_PYTHON=%s' % ('YES' if '+python' in spec else 'NO'),
            '-DBUILD_GRIDGEN=%s' % ('YES' if '+gridgen' in spec else 'NO'),
            '-DBUILD_COUPLER=%s' % ('YES' if '+coupler' in spec else 'NO'),
            '-DUSE_PISM=%s' % ('YES' if '+pism' in spec else 'NO')]

@xjrc
Copy link
Copy Markdown
Member Author

xjrc commented May 14, 2016

@tgamblin: I finished writing the code that adds the setup_py executable to all Python extensions and a script that converts existing uses of python('setup.py', *args) to setup_py(*args) (which can be run and discarded after these changes are merged).

Just a few quick notes about some things that I noticed while making these changes:

  • The py-sip and py-pyqt packages are the only Python extension packages that don't install using the standard python('setup.py', *args) method. These packages are installed using custom install scripts that don't use Python's distutils library (which coordinates with the user/system/distribution configuration files), so they will most likely ignore user configuration even though they don't use setup_py.
  • The --no-user-cfg option is only supported by Python v2.7 and v3.4+ (see this Python issue for details). If any Python version outside of this range is added to Spack, a much more involved solution will be required to prevent user configuration from affecting Spack installs. I've added a warning about this in the Python package when one of these versions is installed.

@citibeth: I've looked over #543 and I think you have a good point about applying a similar subclassing approach for Python packages. My only hangup is that most Python packages just call python('setup.py', (build|install), '--prefix=%s' % prefix) with very little variation, so adding infrastructure to support further customizations seems like it won't add much value for package developers (unlike the CMake case where this is valuable because there are many variations). I suppose that it wouldn't hurt to add a PythonPackage superclass with python('setup.py', 'install', ...) as the default install behavior to remove all of the boilerplate installs from the Python extension packages, but I think that this is orthogonal enough to the intent of this PR to deserve its own PR. What do you think @tgamblin?

@xjrc xjrc changed the title [WIP] Enhancement Proposal: Make Python Spack Installs Ignore User Configuration Enhancement Proposal: Make Python Spack Installs Ignore User Configuration Jun 2, 2016
@xjrc
Copy link
Copy Markdown
Member Author

xjrc commented Jul 21, 2016

@tgamblin: I've updated this pull request so that it no longer conflicts with the develop branch. I retested the [email protected] and [email protected] installs and they seem to still be working after the merge. I had to resolve some nontrivial merge conflicts in the python package file, so any additional testing by other users (particularly anyone that uses the +tk and +ucs4 variants e.g. @adamjstewart, @paulhopkins) would be greatly appreciated.

Please let me know if there are any issues with the merged code and I'll try to fix them as soon as possible!

@tgamblin
Copy link
Copy Markdown
Member

@xjrc: thanks!

@lee218llnl @adamjstewart: does this work for you guys?

@adamjstewart
Copy link
Copy Markdown
Member

There seem to be a lot of unnecessary changes to the Python package that don't affect how it installs nor do they solve flake8 issues. They also make it less future proof by reverting to the old Python 2 string formatting syntax.

@xjrc
Copy link
Copy Markdown
Member Author

xjrc commented Jul 22, 2016

@adamjstewart: Sorry about all of the unnecessary changes; this pull request has been sitting around since before the python package was refactored for flake8 checks, so I had to merge with the refactored version and I used my own changes when the refactoring was equivalent. I certainly don't mind reverting to the current version of the python package and simply introducing the important changes that I made in this PR. In fact, that would probably be better since there would be less errors to worry about. Thoughts?

@adamjstewart
Copy link
Copy Markdown
Member

I figured that was the cause. It would certainly make it easier to review.

@tgamblin
Copy link
Copy Markdown
Member

@lee218llnl, @adamjstewart

@xjrc
Copy link
Copy Markdown
Member Author

xjrc commented Jul 22, 2016

@adamjstewart: I've updated this pull request so that it includes changes that are less intrusive on the python package. I left in a few refactoring changes that I felt were valuable (e.g. the build flag changes in the install method), but if there are any issues with these please let me know.

@tgamblin: This pull request makes the history for the python package incredibly messy, so I'd like to try and rewrite the history before this PR is merged. I'm hoping to have this done within the next hour or so.

@xjrc xjrc force-pushed the packages/python branch from 75f9c13 to fa92f58 Compare July 22, 2016 18:33
@xjrc
Copy link
Copy Markdown
Member Author

xjrc commented Jul 22, 2016

@tgamblin: I just finished cleaning up the history, so this PR should be ready for merging after it has been reviewed.

spec['tk'].prefix.lib, spec['tcl'].prefix.lib
])

dep_pfxs = [dspec.prefix for dspec in spec.dependencies('link')]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, this is such a nicer way of generating a list of dependencies. I'll have to keep this in mind when I'm writing other packages.

@adamjstewart
Copy link
Copy Markdown
Member

LGTM. Aside from running that script on all of the python extensions, I think the last thing that should be done is to edit spack create to use the new default syntax. All you should need to change is this line.

@tgamblin tgamblin merged commit 395c616 into spack:develop Jul 22, 2016
@tgamblin
Copy link
Copy Markdown
Member

@adamjstewart: good suggestion! @xjrc: can you change spack create to use this?

@tgamblin
Copy link
Copy Markdown
Member

@xjrc: thanks for the implementation!

@xjrc
Copy link
Copy Markdown
Member Author

xjrc commented Jul 22, 2016

@adamjstewart, @tgamlin: Thanks to both of you for your help/suggestions! I'll create a pull request for the change to spack create in a couple of minutes.

@adamjstewart
Copy link
Copy Markdown
Member

Uhh, I don't think this was ready to be merged. Weren't we going to run the script that you wrote to regex replace python with setup_py for all python packages?

@xjrc
Copy link
Copy Markdown
Member Author

xjrc commented Jul 22, 2016

It seems to me like the python('setup.py', ...) to setup_py(...) transformation and spack create change would fit well in this PR. Would you prefer to revert and include these changes in this PR or to include them in separate PRs, @tgamblin?

@lee218llnl
Copy link
Copy Markdown
Contributor

Sorry to join in late, but this all looks OK to me. I don't maintain a personal distutils config file, so this hasn't affected me in the past, but I can see this being useful for other users.

@adamjstewart
Copy link
Copy Markdown
Member

@xjrc Either way, the script that you wrote doesn't need to be in the Spack repository. I thought it was just a way to show what you will run before things get merged. I'm glad it's backwards compatible regardless.

@xjrc
Copy link
Copy Markdown
Member Author

xjrc commented Jul 22, 2016

@adamjstewart: My motivation for including the script was to demonstrate how I was changing each Python install (as you mentioned); I didn't really intend for it to remain in the Spack repository indefinitely. In retrospect, I think that it may have been better to just run the script and have all the changes bundled into a this PR. At any rate, I'll be sure to remove this script from Spack when I submit a new PR that finalizes the changes started here.

@adamjstewart adamjstewart mentioned this pull request Sep 12, 2016
olupton pushed a commit to olupton/spack that referenced this pull request Feb 7, 2022
…ort) (spack#950)

 - update llvm package recipe and patches from upstream version 12.0
 - update deploy configs to enable GPU support (CUDA as well as OpenMP offload support)
 - Use NVIDIA GPU default arch 70 (for BB5 Volta GPUs)
 - Update binutils dependency in py-llvmlite with minimal changes to avoid concretiser issues 
    -  this is dependency of py-atlas-building-tools
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants