Skip to content

Commit

Permalink
Add bash command line completion for xAH_run.py in CMake (#1038)
Browse files Browse the repository at this point in the history
* allow for argcomplete with CMake-based releases
* update docs
* inject register-python-arguments into ${ATLAS_PLATFORM}/setup.sh
  • Loading branch information
kratsg committed Sep 27, 2017
1 parent 1299fe9 commit cc623cf
Show file tree
Hide file tree
Showing 7 changed files with 164 additions and 3 deletions.
19 changes: 19 additions & 0 deletions CMakeLists.txt
Expand Up @@ -108,3 +108,22 @@ atlas_add_library( xAODAnaHelpersLib xAODAnaHelpers/*.h Root/*.h Root/*.cxx ${xA
atlas_install_python_modules( python/*.py )
atlas_install_scripts( scripts/*.py )
atlas_install_data( data/* )


### Install python packages
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
include(SetupPythonPackage)

# Install argcomplete:
setup_python_package( argcomplete
"https://pypi.python.org/packages/3b/db/c524f0d72842b44b179cc50d4257f1e72f447fef0919556e8b28a9b0f80f/argcomplete-1.9.2.tar.gz"
"13243e0b88102f13f7537f5aa70a48c0"
PATCH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/patch-setup.cfg setup.cfg
)

add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/xAH_env_copied
COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/cmake/setup.sh >> ${CMAKE_BINARY_DIR}/${ATLAS_PLATFORM}/setup.sh
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_BINARY_DIR}/xAH_env_copied
)
add_custom_target(Setup_xAH_Environment ALL DEPENDS ${CMAKE_BINARY_DIR}/xAH_env_copied)
execute_process(COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_BINARY_DIR}/xAH_env_copied)
75 changes: 75 additions & 0 deletions cmake/SetupPythonPackage.cmake
@@ -0,0 +1,75 @@
### Install python packages

# for setuptools
find_package( pytools )

# Helper macro for building and installing the packages. Documentation
# to be written later...
function( setup_python_package name file md5 )

# Parse the optional argument(s):
cmake_parse_arguments( ARG "SINGLE_VERSION" ""
"DEPENDS;EXTRA_ARGS;PATCH" ${ARGN} )

# Extra argument(s) for the installation:
if( ARG_SINGLE_VERSION )
set( _extraArg )
else()
set( _extraArg --single-version-externally-managed )
endif()

if ( ARG_PATCH )
set( _patchCmd PATCH_COMMAND patch -p1 < ${ARG_PATCH} )
endif()

# Build the package with the help of python's distutils:
ExternalProject_Add( ${name}
PREFIX ${CMAKE_BINARY_DIR}
URL ${file}
URL_MD5 ${md5}
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E echo
"Configuring the build of ${name}"
${_patchCmd}
BUILD_COMMAND ${CMAKE_BINARY_DIR}/atlas_build_run.sh
python setup.py ${ARG_EXTRA_ARGS} build
INSTALL_COMMAND ${CMAKE_COMMAND} -E make_directory
${CMAKE_PYTHON_OUTPUT_DIRECTORY}
COMMAND ${CMAKE_COMMAND} -E make_directory
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
COMMAND ${CMAKE_BINARY_DIR}/atlas_build_run.sh
python setup.py ${ARG_EXTRA_ARGS} install
--prefix ${CMAKE_BINARY_DIR}/${ATLAS_PLATFORM}
--exec-prefix ${CMAKE_BINARY_DIR}/${ATLAS_PLATFORM}
--root /
--install-lib ${CMAKE_PYTHON_OUTPUT_DIRECTORY}
--install-scripts ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
${_extraArg} )

# Make the package target depend on this one:
add_dependencies( Package_xAODAnaHelpers ${name} )

# Add possible extra dependencies:
if( ARG_DEPENDS )
add_dependencies( ${name} ${ARG_DEPENDS} )
endif()

# Get the package directory:
atlas_get_package_dir( pkgDir )

# Add some metadata to the target:
set_property( TARGET ${name} PROPERTY LABEL xAODAnaHelpers )
set_property( TARGET ${name} PROPERTY FOLDER ${pkgDir} )

# Generate the package installer script:
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkgbuildInstall.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/${name}PkgbuildInstall.cmake
@ONLY )

# Use this script for installing the package:
install( SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/${name}PkgbuildInstall.cmake )

endfunction( setup_python_package )

# Clean up:
unset( setup_python_package )
8 changes: 8 additions & 0 deletions cmake/patch-setup.cfg
@@ -0,0 +1,8 @@
--- setup.cfg-orig 2017-09-27 10:58:54.738687009 -0500
+++ setup.cfg 2017-09-27 10:59:06.210122091 -0500
@@ -17,3 +17,5 @@
tag_build =
tag_date = 0

+[build]
+executable = /usr/bin/env python
50 changes: 50 additions & 0 deletions cmake/pkgbuildInstall.cmake.in
@@ -0,0 +1,50 @@
# $Id: pkgbuildInstall.cmake.in 720559 2016-01-29 09:13:32Z krasznaa $
#
# Script installing a setuptools / distutils based Python package
# during the release installation, under $CMAKE_INSTALL_PREFIX.
#

# Get the destination directory as an absolute path, as the setup.py script
# can't deal with relative paths correctly.
if( NOT "$ENV{DESTDIR}" STREQUAL "" )
get_filename_component( _destdir $ENV{DESTDIR} ABSOLUTE )
endif()

# Install the package:
execute_process( COMMAND ${CMAKE_BINARY_DIR}/atlas_build_run.sh
python setup.py @ARG_EXTRA_ARGS@ install
--prefix ${_destdir}${CMAKE_INSTALL_PREFIX}
--exec-prefix ${_destdir}${CMAKE_INSTALL_PREFIX}
--root /
--install-lib ${_destdir}${CMAKE_INSTALL_PREFIX}/@CMAKE_INSTALL_PYTHONDIR@
--install-scripts ${_destdir}${CMAKE_INSTALL_PREFIX}/@CMAKE_INSTALL_BINDIR@
--record @CMAKE_CURRENT_BINARY_DIR@/@name@_installed.files
@_extraArg@
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src/@name@ )

# Read in the list of installed files, and select ones put into the
# binary directory.
file( READ @CMAKE_CURRENT_BINARY_DIR@/@name@_installed.files
_installedFiles LIMIT 10000000 )
string( SUBSTRING "${_destdir}${CMAKE_INSTALL_PREFIX}/@CMAKE_INSTALL_BINDIR@"
1 -1 _binDir )
string( REGEX MATCHALL "(^|\n)${_binDir}[^\n]+" _executables
${_installedFiles} )

# Loop over the installed executables:
foreach( _exec ${_executables} )
# And replace the absolute python executable names in them with
# relocatable ones.
string( STRIP ${_exec} _execName )
# This is unfortunately very unportable. But should be hopefully good
# enough on all POSIX platforms at least.
execute_process( COMMAND
sed "s/^#!\\/.*\\/python/#!\\/usr\\/bin\\/env python/"
"/${_execName}"
COMMAND tee /${_execName}Fixed
COMMAND ${CMAKE_COMMAND} -E rename "/${_execName}Fixed" "/${_execName}" )
# For some reason this doesn't work correctly (in CMake 3.3.2) when put at
# the end of the previous execute_process(...) call. Only when used in a
# separate call...
execute_process( COMMAND chmod 755 /${_execName} )
endforeach()
3 changes: 3 additions & 0 deletions cmake/setup.sh
@@ -0,0 +1,3 @@

# xAODAnaHelpers injected shell commands are below
eval "$(register-python-argcomplete xAH_run.py)"
5 changes: 5 additions & 0 deletions docs/UsingUs.rst
Expand Up @@ -114,6 +114,11 @@ to see all the help information.
API Reference
-------------

.. note:: If you are using a CMake-based release, or you have ``argcomplete`` in your python environment, you can enable automatic completion of the options. For example, running something like this::

eval "$(register-python-argcomplete xAH_run.py)"


.. argparse::
:ref: xAH_run.parser
:prog: xAH_run.py
Expand Down
7 changes: 4 additions & 3 deletions scripts/xAH_run.py
Expand Up @@ -15,15 +15,14 @@
#TODO: move into __main__

import argparse
try: import argcomplete
except: pass
import os
import subprocess
import sys
import datetime
import time

# think about using argcomplete
# https://argcomplete.readthedocs.org/en/latest/#activating-global-completion%20argcomplete

# if we want multiple custom formatters, use inheriting
class CustomFormatter(argparse.ArgumentDefaultsHelpFormatter):
pass
Expand Down Expand Up @@ -215,6 +214,8 @@ def __call__(self, parser, namespace, values, option_string=None):
if __name__ == "__main__":
SCRIPT_START_TIME = datetime.datetime.now()

try: argcomplete.autocomplete(parser)
except: pass
# parse the arguments, throw errors if missing any
args = parser.parse_args()

Expand Down

0 comments on commit cc623cf

Please sign in to comment.