Source code for mmf.utils.run

r"""Running Programs

This module is intended to be used to manage important runs that generate data
for a paper, etc.

For interactive use, start python as follows::

   python -im mmf.utils.run

If you need to run a script, then use this module as the startup file with one
of the following commands::

   PYTHONSTARTUP=path_to_mmf/mmf/utils/run.py python file.py
   PYTHONSTARTUP=path_to_mmf/mmf/utils/run.py python -c "import blah;..."

To find the full path for the previous commands, run::

   python -c"import sys;sys._pymmf_no_init=True;import mmf;print mmf.run_cmd()"

This can be aliased for easy use.

Purpose
-------
The aim of this module is reproducibility:
1) This module assumes that the application be run in an appropriately named
   directory: no special sub-directory will be created (other than those
   associated with :class:`mmf.archive.DataSet` instances).  
2) The command must be run in a mercurial repository with no outstanding
   commits.  The current revision number and checksum is used for output.  These
   checks can be temporarily disabled by setting the environmental variable
   `STRICT=false`, but this should be avoided except during testing as it breaks
   the reproducibility.
3) All input and output is recorded.
4) ``pip`` is used to record the versions of libraries installed when the
   program is run.

"""
import os.path
import subprocess
import sys

[docs]def run_cmd(): r"""Return the run command for running python with this module as the startup file.""" return 'PYTHONSTARTUP="' + os.path.realpath(__file__) + '" python'
[docs]def get_hg_checksum(strict=True): r"""Return a string of the form `<rev>_<checksum>` where `<rev>` is the local revision number and `<checksum>` is the checksum of the current revision. (Note: `<rev>` is not unique and may vary from repository to repository, but provides a simple chronological ordering for runs that is not intuitively deducible from the `<checksum>`.) Parameters ---------- strict : bool If `True`, then this will raise a :exc:`ValueError` exception if the there are uncommited changes. """ try: subprocess.check_output(["hg","--version"]).strip() except: print("ERROR: Could not execute Mercurial (hg)!") raise try: hg_checksum = subprocess.check_output(["hg","-q","id"]).strip() except: print("ERROR: Could not get version! (Is there are repository here?)") raise try: hg_local_revision = subprocess.check_output(["hg","id","-n"]).strip() except: print("ERROR: Could not get local revision!") raise if len(hg_checksum) not in [12, 13]: raise ValueError( 'Please run from within the mercurial repo. "hg -1 id" gave:\n' + hg_checksum) if (strict and hg_checksum.endswith('+')): raise ValueError( 'Repository has uncommited changes! ' + 'Commit ("hg com") before running.') hg_checksum = "%s_%s" % (hg_local_revision, hg_checksum) return hg_checksum
[docs]def get_pip_requirements(): r"""Return the ``pip`` requirements file as a string."""
if "__main__" == __name__: strict = (os.environ.get('STRICT', "True").lower() != "false") hg_checksum = get_hg_checksum(strict) print hg_checksum