Package Gnumed :: Package pycommon :: Module gmNull |
[frames] | no frames]

# Source Code for Module Gnumed.pycommon.gmNull

      1  """null.py
      2
      3  This is a sample implementation of the 'Null Object' design pattern.
      4
      5  Roughly, the goal with Null objects is to provide an 'intelligent'
      6  replacement for the often used primitive data type None in Python or
      7  Null (or Null pointers) in other languages. These are used for many
      8  purposes including the important case where one member of some group
      9  of otherwise similar elements is special for whatever reason. Most
     10  often this results in conditional statements to distinguish between
     11  ordinary elements and the primitive Null value.
     12
     13  Among the advantages of using Null objects are the following:
     14
     15    - Superfluous conditional statements can be avoided
     16          by providing a first class object alternative for
     17          the primitive value None.
     18
     19    - Code readability is improved.
     20
     21    - Null objects can act as a placeholder for objects
     22          with behaviour that is not yet implemented.
     23
     24    - Null objects can be replaced for any other class.
     25
     26    - Null objects are very predictable at what they do.
     27
     28  To cope with the disadvantage of creating large numbers of passive
     29  objects that do nothing but occupy memory space Null objects are
     30  often combined with the Singleton pattern.
     31
     32  For more information use any internet search engine and look for
     33  combinations of these words: Null, object, design and pattern.
     34
     35  Dinu C. Gherman,
     36  August 2001
     37
     38  Karsten Hilbert
     39  July 2004
     40  """
     41  #==============================================================
     42  __author__ = "Dinu C. Gherman, Karsten Hilbert"
     43  __license__ = "GPL v2 or later (details at http://www.gnu.org)"
     44
     45  import logging
     46
     47  _log = logging.getLogger('cNull')
     48
     49  #==============================================================
     50 -class cNull(object):
     51          """A class for implementing Null objects.
     52
     53          This class ignores all parameters passed when constructing or
     54          calling instances and traps all attribute and method requests.
     55          Instances of it always (and reliably) do 'nothing'.
     56
     57          The code might benefit from implementing some further special
     58          Python methods depending on the context in which its instances
     59          are used. Especially when comparing and coercing Null objects
     60          the respective methods' implementation will depend very much
     61          on the environment and, hence, these special methods are not
     62          provided here.
     63          """
     64          # object constructing
     65 -        def __init__(self, *args, **kwargs):
     66                  "Ignore parameters."
     67                  _log.debug('args: %s', args)
     68                  _log.debug('kwargs: %s', kwargs)
     69
     70          # object calling
     71 -        def __call__(self, *args, **kwargs):
     72                  "Ignore method calls."
     73                  _log.debug('args: %s', args)
     74                  _log.debug('kwargs: %s', kwargs)
     75                  return self
     76
     77          # attribute handling
     78 -        def __getattr__(self, attribute):
     79                  "Ignore attribute requests."
     80                  _log.debug('%s.%s', self, attribute)
     81                  return self
     82
     83 -        def __setattr__(self, attribute, value):
     84                  "Ignore attribute setting."
     85                  _log.debug('%s.%s = %s', self, attribute, value)
     86                  return self
     87
     88 -        def __delattr__(self, attribute):
     89                  "Ignore deleting attributes."
     90                  _log.debug('%s.%s', self, attribute)
     91                  return self
     92
     93          # item handling
     94 -        def __getitem__(self, item):
     95                  "Ignore item requests."
     96                  _log.debug('%s[%s]', self, item)
     97                  return self
     98
     99 -        def __setitem__(self, item, value):
    100                  "Ignore item setting."
    101                  _log.debug('%s[%s] = %s', self, item, value)
    102                  return self
    103
    104 -        def __delitem__(self, item):
    105                  "Ignore deleting items."
    106                  _log.debug('%s[%s]', self, item)
    107                  return self
    108
    109          # misc.
    110 -        def __repr__(self):
    111                  "Return a string representation."
    112                  return "<cNull instance @ %s>" % id(self)
    113
    114 -        def __str__(self):
    115                  "Convert to a string and return it."
    116                  return '<cNull instance>'
    117
    118 -        def __nonzero__(self):
    119                  _log.debug('returns 0')
    120                  return 0
    121
    122 -        def __len__(self):
    123                  _log.debug('0')
    124                  return 0
    125
    126  #==============================================================
    127 -def test():
    128          "Perform some decent tests, or rather: demos."
    129
    130          # constructing and calling
    131
    132          n = cNull()
    133          n = cNull('value')
    134          n = cNull('value', param='value')
    135
    136          n()
    137          n('value')
    138          n('value', param='value')
    139
    140          # attribute handling
    141
    142          n.attr1
    143          n.attr1.attr2
    144          n.method1()
    145          n.method1().method2()
    146          n.method('value')
    147          n.method(param='value')
    148          n.method('value', param='value')
    149          n.attr1.method1()
    150          n.method1().attr1
    151
    152          n.attr1 = 'value'
    153          n.attr1.attr2 = 'value'
    154
    155          n['1']
    156          n['2'] = '123'
    157          del n['3']
    158
    159          del n.attr1
    160          del n.attr1.attr2.attr3
    161
    162          # representation and conversion to a string
    163          tmp = '<cNull instance @ %s>' % id(n)
    164          assert repr(n) == tmp
    165          assert str(n) == '<cNull instance>'
    166
    167          # comparing
    168          if n == 1:
    169                  print("Null object == 1")
    170          else:
    171                  print("Null object != 1")
    172
    173  #--------------------------------------------------------------
    174  if __name__ == '__main__':
    175
    176          import sys
    177
    178          if len(sys.argv) < 2:
    179                  sys.exit()
    180
    181          if sys.argv[1] != 'test':
    182                  sys.exit()
    183
    184          test()
    185