[py-svn] r24601 - py/dist/py/documentation

pinard at codespeak.net pinard at codespeak.net
Mon Mar 20 15:17:04 CET 2006


Author: pinard
Date: Mon Mar 20 15:17:02 2006
New Revision: 24601

Added:
   py/dist/py/documentation/log.txt
Log:
* documentation/log.txt: New.


Added: py/dist/py/documentation/log.txt
==============================================================================
--- (empty file)
+++ py/dist/py/documentation/log.txt	Mon Mar 20 15:17:02 2006
@@ -0,0 +1,211 @@
+.. role:: code(strong)
+.. role:: file(literal)
+
+========================================
+:code:`py.log` documentation and musings
+========================================
+
+.. contents::
+.. sectnum::
+
+Foreword
+========
+
+I attempt here to briefly state the actual specification of the
+:code:`py.log` module, as currently found within the nice and fertile
+`py library`__ project.  I also want to either present or summarize a
+few ideas for improving or developping this module further.
+
+__ http://codespeak.net/py/current/doc/home.html
+
+This document is meant to trigger or facilitate discussions.  It shamelessly
+steals from the `Agile Testing`__ comments, and from other sources as well,
+without really trying to sort them out.
+
+__ http://agiletesting.blogspot.com/2005/06/keyword-based-logging-with-py-library.html
+
+My knowledge of English is fairly rough and approximative, I hope
+readers will kindly and spontaneously offer stylistic corrections.
+
+Logging organisation
+====================
+
+Le :code:`py.log` module aims a niche comparable to the one of the
+`logging module`__ as found within standard Python distributions, yet
+with much simpler paradigms for configuration and usage.
+
+__ http://www.python.org/doc/2.4.2/lib/module-logging.html
+
+Holger Krekel, the main :code:`py` library developer, introduced
+the idea of keyword-based logging and of logging *producers* and
+*consumers*.  A log producer is an object used by the application code
+to send messages to various log consumers.  When you create a log
+producer, you define a set of keywords that are then used to both route
+the logging messages to consumers, and to prefix those messages.
+
+In fact, each log producer has a few keywords associated with it for
+identification purposes.  These keywords form a tuple of strings, and
+may be used to later retrieve a particular log producer.
+
+A log producer may (or may not) be associated with a log consumer, meant
+to handle log messages in particular ways.  The log consumers can be
+``STDOUT``, ``STDERR``, log files, syslog, the Windows Event Log, user
+defined functions, etc.  (Yet, logging to syslog or to the Windows Event
+Log is only future plans for now).  A log producer has never more than
+one consumer at a given time, but it is possible to dynamically switch
+a producer to use another consumer.  On the other hand, a single log
+consumer may be associated with really many producers.
+
+Note that creating and associating a producer and a consumer is done
+automatically when not otherwise overriden, so using :code:`py` logging
+is quite comfortable even in the smallest programs.  More typically,
+the application programmer will likely design a hierarchy of producers,
+and will select keywords appropriately for marking the hierarchy tree.
+If a node of the hierarchical tree of producers has to be divided in
+sub-trees, all producers in the sub-trees have keywords which share,
+as a common prefix, the keywords of the node being divided.  In other
+words, we go further down in the hierarchy of producers merely by adding
+keywords.
+
+Using the :code:`py.log` library
+================================
+
+For using the :code:`py.log` library, the user ought to import it into a
+Python application, have at least one log producer and one log consumer
+created, have producers and consumers associated, and finally call log
+producers as needed, giving them log messages.
+
+Importing it
+------------
+
+Once the :code:`py` library installed on your system, a mere::
+
+  import py
+
+holds enough magic for lazily importing the various facilities of the
+:code:`py` library when they are first needed.  This is really how
+:code:`py.log` is made available to the application.  For example, after
+the above ``import py``, one may directly write ``py.log.Producer(...)``
+and everything should work fine, the user does not have to worry about
+specifically importing more modules.
+
+Creating a producer
+-------------------
+
+There are three ways for creating a log producer instance:
+
+  + As soon as ``py.log`` is first evaluated within an application
+    program, a default log producer is created, and made available under
+    the name ``py.log.default``.  The keyword ``default`` is associated
+    with that producer.
+
+  + The ``py.log.Producer()`` constructor may be explicitly called
+    for creating a new instance of a log producer.  That constructor
+    accepts, as an argument, the keywords that should be associated with
+    that producer.  Keywords may be given either as a tuple of keyword
+    strings, or as a single space-separated string of keywords.
+
+  + Whenever an attribute is *taken* out of a log producer instance,
+    for the first time that attribute is taken, a new log producer is
+    created.  The keywords associated with that new producer are those
+    of the initial producer instance, to which is appended the name of
+    the attribute being taken.
+
+The last point is especially useful, as it allows using log producers
+without further declarations, merely creating them *on-the-fly*.
+
+Creating a consumer
+-------------------
+
+There are many ways for creating or denoting a log consumer:
+
+  + A default consumer exists within the ``py.log`` facilities, which
+    has the effect of writing log messages on the Python standard output
+    stream.  That consumer is associated at the very top of the producer
+    hierarchy, and as such, is called whenever no other consumer is
+    found.
+
+  + The notation ``log.STDOUT`` accesses a log consumer which writes log
+    messages on the Python standard output stream.
+
+  + The notation ``log.STDERR`` accesses a log consumer which writes log
+    messages on the Python standard error stream.
+
+  + The ``log.File()`` constructor accepts, as argument, either a file
+    already opened in write mode or any similar file-like object, and
+    creates a log consumer able to write log messages onto that file.
+
+  + The ``log.Path()`` constructor accepts a file name for its first
+    argument, and creates a log consumer able that will write log messages
+    into a file by that name, creating it as necessary.
+
+    The constructor call also accepts a few keyword parameters:
+
+      + ``append``, which is False by default, may be used for opening the
+        file in append mode instead of write mode.
+
+      + ``delayed_create``, which is False by default, maybe be used for
+        opening the file at the latest possible time.  Consequently, the
+        file will not be created if it did not exist, and no actual log
+        message gets written to it.
+
+      + ``buffering``, which is 1 by default, is used when opening the
+        file.  Buffering can be turned off by specifying a 0 value.  The
+        buffer size may also be selected through this argument.
+
+  + Any user defined function may be used for a log consumer.  Such a
+    function should accept a single argument, which is the message to
+    write, and do whatever is deemed appropriate by the programmer.
+    When the need arises, this may be an especially useful and flexible
+    feature.
+
+  + The special value ``None`` means no consumer at all.  This acts just
+    like if there was a consumer which would silently discard all log
+    messages sent to it.
+
+Associating producers and consumers
+-----------------------------------
+
+Each log producer may have at most one log consumer associated with
+it.  A log producer gets associated with a log consumer through the
+``set_consumer()`` method of the log producer.  That method accepts
+a single argument, specifying the precise consumer to use for that
+producer.  Until this method is called for a producer, that producer
+does not have any explicit consumer associated with it.
+
+Now, the hierarchy of log producers establishes which consumer gets used
+whenever a producer has not explicit consumer.  When a log producer
+has no consumer explicitly associated with it, it dynamically and
+recursively inherits the consumer of its parent node, that is, that node
+being a bit closer to the root of the hierarchy.  In other words, the
+rightmost keywords of that producer are dropped until another producer
+is found which has an explicit consumer.  A nice side-effect is that,
+by explicitly associating a consumer with a producer, all consumer-less
+producers which appear under that producer, in the hierarchy tree,
+automatically *inherits* that consumer.
+
+Writing log messages
+--------------------
+
+All log producer instances are also functions, and this is by calling
+them that log messages are generated.  Each call to a producer object
+produces the text for one log entry, which in turn, is sent to the log
+consumer for that producer.
+
+The log entry displays, after a prefix identifying the log producer
+being used, all arguments given in the call, converted to strings and
+space-separated.  (This is meant by design to be fairly similar to what
+the ``print`` statement does in Python).  The prefix itself is made up
+of a colon-separated list of keywords associated with the producer, the
+whole being set within square brackets.
+
+Note that the consumer is responsible for adding the newline at the end
+of the log entry.  That final newline is not part of the text for the
+log entry.
+
+Other details
+-------------
+
++ Should speak about pickle-ability of :code:`py.log`.
+
++ What is :code:``log.get`` (in :file:`logger.py`)?



More information about the pytest-commit mailing list