diff --git a/ckan/lib/util.py b/ckan/lib/util.py new file mode 100644 index 00000000000..86d9c0e3d95 --- /dev/null +++ b/ckan/lib/util.py @@ -0,0 +1,45 @@ +'''Shared utility functions for any Python code to use. + +Unlike :py:func:`ckan.lib.helpers`, the functions in this module are not +available to templates. + +''' +import subprocess + + +# We implement our own check_output() function because +# subprocess.check_output() isn't in Python 2.6. +# This code is copy-pasted from Python 2.7 and adapted to make it work with +# Python 2.6. +# http://hg.python.org/cpython/file/d37f963394aa/Lib/subprocess.py#l544 +def check_output(*popenargs, **kwargs): + r"""Run command with arguments and return its output as a byte string. + + If the exit code was non-zero it raises a CalledProcessError. The + CalledProcessError object will have the return code in the returncode + attribute and output in the output attribute. + + The arguments are the same as for the Popen constructor. Example: + + >>> check_output(["ls", "-l", "/dev/null"]) + 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n' + + The stdout argument is not allowed as it is used internally. + To capture standard error in the result, use stderr=STDOUT. + + >>> check_output(["/bin/sh", "-c", + ... "ls -l non_existent_file ; exit 0"], + ... stderr=STDOUT) + 'ls: non_existent_file: No such file or directory\n' + """ + if 'stdout' in kwargs: + raise ValueError('stdout argument not allowed, it will be overridden.') + process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs) + output, unused_err = process.communicate() + retcode = process.poll() + if retcode: + cmd = kwargs.get("args") + if cmd is None: + cmd = popenargs[0] + raise subprocess.CalledProcessError(retcode, cmd) + return output diff --git a/ckan/new_tests/test_coding_standards.py b/ckan/new_tests/test_coding_standards.py index 46890f1793e..e27018c9c61 100644 --- a/ckan/new_tests/test_coding_standards.py +++ b/ckan/new_tests/test_coding_standards.py @@ -8,42 +8,7 @@ ''' import subprocess - -# We implement our own check_output() function because -# subprocess.check_output() isn't in Python 2.6. -# This code is copy-pasted from Python 2.7: -# http://hg.python.org/cpython/file/d37f963394aa/Lib/subprocess.py#l544 -def check_output(*popenargs, **kwargs): - r"""Run command with arguments and return its output as a byte string. - - If the exit code was non-zero it raises a CalledProcessError. The - CalledProcessError object will have the return code in the returncode - attribute and output in the output attribute. - - The arguments are the same as for the Popen constructor. Example: - - >>> check_output(["ls", "-l", "/dev/null"]) - 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n' - - The stdout argument is not allowed as it is used internally. - To capture standard error in the result, use stderr=STDOUT. - - >>> check_output(["/bin/sh", "-c", - ... "ls -l non_existent_file ; exit 0"], - ... stderr=STDOUT) - 'ls: non_existent_file: No such file or directory\n' - """ - if 'stdout' in kwargs: - raise ValueError('stdout argument not allowed, it will be overridden.') - process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs) - output, unused_err = process.communicate() - retcode = process.poll() - if retcode: - cmd = kwargs.get("args") - if cmd is None: - cmd = popenargs[0] - raise subprocess.CalledProcessError(retcode, cmd, output=output) - return output +import ckan.lib.util as util def test_building_the_docs(): @@ -52,17 +17,17 @@ def test_building_the_docs(): This test unfortunately does take quite a long time to run - rebuilding the docs from scratch just takes a long time. - This test will also fail is build_sphinx exits with non-zero status - (because subprocess.check_output() will raise an exception). + This test will also fail is build_sphinx exits with non-zero status. ''' try: - output = check_output( + output = util.check_output( ['python', 'setup.py', 'build_sphinx', '--all-files', '--fresh-env'], stderr=subprocess.STDOUT) except subprocess.CalledProcessError as err: - assert False, "Building the docs failed: {err}".format( - err=err.message + ' ' + err.output) + assert False, ( + "Building the docs failed with return code: {code}".format( + code=err.returncode)) output_lines = output.split('\n') errors = [line for line in output_lines if 'ERROR' in line] diff --git a/doc/conf.py b/doc/conf.py index d49b38a6fa0..c1e1b93fc40 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -18,6 +18,8 @@ import os import subprocess +import ckan.lib.util as util + # If your extensions (or modules documented by autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. @@ -115,43 +117,6 @@ release = ckan.__version__ -# We implement our own check_output() function because -# subprocess.check_output() isn't in Python 2.6. -# This code is copy-pasted from Python 2.7: -# http://hg.python.org/cpython/file/d37f963394aa/Lib/subprocess.py#l544 -def check_output(*popenargs, **kwargs): - r"""Run command with arguments and return its output as a byte string. - - If the exit code was non-zero it raises a CalledProcessError. The - CalledProcessError object will have the return code in the returncode - attribute and output in the output attribute. - - The arguments are the same as for the Popen constructor. Example: - - >>> check_output(["ls", "-l", "/dev/null"]) - 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n' - - The stdout argument is not allowed as it is used internally. - To capture standard error in the result, use stderr=STDOUT. - - >>> check_output(["/bin/sh", "-c", - ... "ls -l non_existent_file ; exit 0"], - ... stderr=STDOUT) - 'ls: non_existent_file: No such file or directory\n' - """ - if 'stdout' in kwargs: - raise ValueError('stdout argument not allowed, it will be overridden.') - process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs) - output, unused_err = process.communicate() - retcode = process.poll() - if retcode: - cmd = kwargs.get("args") - if cmd is None: - cmd = popenargs[0] - raise subprocess.CalledProcessError(retcode, cmd, output=output) - return output - - def latest_release_tag(): '''Return the name of the git tag for the latest stable release. @@ -160,7 +125,7 @@ def latest_release_tag(): This requires git to be installed. ''' - git_tags = check_output( + git_tags = util.check_output( ['git', 'tag', '-l'], stderr=subprocess.STDOUT).split() # FIXME: We could do more careful pattern matching against ckan-X.Y.Z here.