.. -*-rst-*-

C
=

The C implementations should follow the `kernel/git coding style
<http://www.kernel.org/doc/Documentation/CodingStyle>`_.


Python
======

Python code follows `PEP8 <http://www.python.org/dev/peps/pep-0008/>`_
with regard to coding style and `PEP257
<http://www.python.org/dev/peps/pep-0257/>`_ with regard to docstring
style. Multi-line docstrings should have one short summary line,
followed by a blank line and a series of paragraphs. The last
paragraph should be followed by a line that closes the docstring (no
blank line in between). Here's an example from
``lib/bup/helpers.py``::

  def unlink(f):
      """Delete a file at path 'f' if it currently exists.

      Unlike os.unlink(), does not throw an exception if the file didn't already
      exist.
      """
      ...

Module-level docstrings follow exactly the same guidelines but without the
blank line between the summary and the details.


Exception Handling
------------------

Avoid finally: blocks in favor of explict catches because a throw
from a finally block will lose any pending exception.  An explicit
catch can chain it (see below).

To behave similarly under Python 2 and 3, use add_ex_tb() to
explicitly add stack traces to any exceptions that are going to be
re-raised by anything other than a no-argument raise (otherwise the
stack trace will be lost)::

  try:
      ...
  except ... as ex:
      add_ex_tb(ex)
      pending_ex = ex
  ...
  raise pending_ex

When an exception is thrown from an exception handler, the pending
exception should be the `"context"
<https://docs.python.org/3/reference/simple_stmts.html#the-raise-statement>`_
of the new exception, which can be accomplished (portably) via
``pending_raise()``::

  try:
      ...
  except ... as ex:
      with pending_raise(ex):
          clean_up()

This should do roughly the same thing in Python 2 and Python 3,
throwing any exception from ``clean_up()`` after adding ex as the
``__context__`` if clean_up() throws, and throwing ``ex`` otherwise.

If for some reason, you need more control, you can use
``add_ex_ctx()`` directly::

  try:
      ...
  except ... as ex:
      add_ex_tb(ex)
      try:
          ...
      except ... as ex2:
          add_ex_tb(ex2)
          raise add_ex_ctx(ex2, ex)
      raise

See the end of ``lib/bup/compat.py`` for a functional example, and all
of this can be removed once we drop support for Python 2.
