Source code for gromacs.environment

# GromacsWrapper environment.py
# Copyright (c) 2011 Oliver Beckstein <orbeckst@gmail.com>
# Released under the GNU Public License 3 (or higher, your choice)
# See the file COPYING for details.

"""
:mod:`gromacs.environment` -- Run time modification of behaviour
================================================================

Some aspects of GromacsWrapper can be determined globally. The
corresponding flags :class:`Flag` are set in the environment (think of
them like environment variables). They are accessible through the
pseudo-dictionary :data:`gromacs.environment.flags`.

The entries appear as 'name'-'value' pairs. Flags check values and illegal ones
raise a :exc:`ValueError`. Documentation on all flags can be obtained with ::

 print gromacs.environment.flags.doc()


List of GromacsWrapper flags with default values
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. autoclass:: flagsDocs


Classes
~~~~~~~

.. data:: flags

.. autoclass:: Flags
   :members:

.. autoclass:: Flag
   :members:

"""


# set up flags for core routines (more convoluted than strictly necessary but should
# be clean to add more flags if needed)
[docs] class Flags(dict): """Global registry of flags. Acts like a dict for item access. There are a number flags defined that influence how GromacsWrapper behaves. They are accessible through the pseudo-dictionary :data:`gromacs.environment.flags` The entries appear as 'name'-'value' pairs. Flags check values and illegal ones raise a :exc:`ValueError`. Documentation on all flags can be obtained with :: print gromacs.environment.flags.__doc__ New flags are added with the :meth:`Flags.register` method which takes a new :class:`Flag` instance as an argument. """ def __init__(self, *args): """For **developers**: Initialize Flags registry with a *list* of :class:`Flag` instances.""" super(Flags, self).__init__([(flag.name, flag) for flag in args]) def get_flag(self, name): return super(Flags, self).__getitem__(name)
[docs] def doc(self): """Shows doc strings for all flags.""" return "\n\n".join([flag.__doc__ for flag in self._itervalues()])
[docs] def register(self, flag): """Register a new :class:`Flag` instance with the Flags registry.""" super(Flags, self).__setitem__(flag.name, flag)
[docs] def update(self, *flags): """Update Flags registry with a list of :class:`Flag` instances.""" super(Flags, self).update([(flag.name, flag) for flag in flags])
[docs] def setdefault(self, k, d=None): raise NotImplementedError
def __getitem__(self, name): return self.get_flag(name).get() def __setitem__(self, name, value): self.get_flag(name).set(value) def _itervalues(self): return super(Flags, self).values() def _items(self): return super(Flags, self).items() def itervalues(self): for flag in self._itervalues(): yield flag.value def iteritems(self): for flag in self._itervalues(): yield flag.name, flag.value
[docs] def values(self): return [flag.value for flag in self._itervalues()]
[docs] def items(self): return [(flag.name, flag.value) for flag in self._itervalues()]
def __repr__(self): return str(self.items())
class FlagsDynamicDocs(Flags): # docs are generated on the fly for interactive use; but because # this does not work well with the sphinx documentation system # ("AttributeError: 'property' object has no attribute # 'expandtabs'") we split the class... @property def __doc__(self): # generate dynamic docs on all flags return self.doc() class IdentityMapping(dict): def __getitem__(self, key): return key
[docs] class Flag(object): """A Flag, essentially a variable that knows its default and legal values.""" def __init__(self, name, default, mapping=None, doc=None): """Create a new flag which will be registered with Flags. Usage :: newflag = Flag(name, default, mapping, doc) :Arguments: *name* name of the flag, must be a legal python name *default* default value *mapping* dict that maps allowed input values to canonical values; if ``None`` then no argument checking will be performed and all values are directly set. *doc* doc string; may contain string interpolation mappings for:: %%(name)s name of the flag %%(default)r default value %%(value)r current value %%(mapping)r mapping Doc strings are generated dynamically and reflect the current state. """ self.name = name self.value = default self.default = default # {v1:v1,v2:v1,v3:v3, ...} mapping of allowed values to canonical ones self.mapping = mapping or IdentityMapping() self._doctemplate = "**%(name)s** = *%(value)r*\n" + ( doc or "*undocumented flag*" ) def get(self): return self.value def set(self, value): if value is not None: try: self.value = self.mapping[value] except KeyError: raise ValueError( "flag must be None or one of " + str(self.mapping.keys()) ) return self.get()
[docs] def prop(self): """Use this for ``property(**flag.prop())``""" return {"fget": self.get, "fset": self.set, "doc": self.__doc__}
def __repr__(self): return """Flag('{name!s}',{value!r})""".format(**self.__dict__)
class _Flag(Flag): @property def __doc__(self): # generate dynamic docs with current values return self._doctemplate % self.__dict__ _flags = [ _Flag( "capture_output", False, { True: True, False: False, "file": "file", }, """ Select if Gromacs command output is *always* captured. >>> flags['%(name)s'] = %(value)r By default a :class:`~gromacs.core.GromacsCommand` will direct STDOUT and STDERR output from the command itself to the screen (through /dev/stdout and /dev/stderr). When running the command, this can be changed with the keywords *stdout* and *stderr* as described in :mod:`gromacs.core` and :class:`~gromacs.core.Command`. If this flag is set to ``True`` then by default STDOUT and STDERR are captured as if one had set :: stdout=False, stderr=False Explicitly setting *stdout* and/or *stderr* overrides the behaviour described above. If set to the special keyword ``"file"` then the command writes to the file whose name is given by ``flags['capture_output_filename']``. This file is *over-written* for each command. In this way one can investigate the output from the last command (presumably because it failed). STDOUT and STDERR are captured into this file by default. STDERR is printed first and then STDOUT, which does not necessarily reflect the order of output one would see on the screen. The default is %(default)r. """, ), _Flag( "capture_output_filename", "gromacs_captured_output.txt", doc=""" Name of the file that captures output if ``flags['capture_output'] = "file"`` >>> flags['%(name)s'] = %(value)r This is an *experimental* feature. The default is %(default)r. """, ), ] #: Global flag registry for :mod:`gromacs.environment`. #: Can be accessed like a dictionary and appears to the casual user as such. flags = FlagsDynamicDocs(*_flags) del _flags # only for sphinx docs
[docs] class flagsDocs(object): __doc__ = flags.doc()