1 2# NOTE: Documentation is intended to be processed by epydoc and contains 3# epydoc markup. 4 5""" 6Overview 7======== 8 9The ``grizzled.misc`` module contains miscellanous functions and classes that 10don't seem to fit well in other modules. 11""" 12 13__docformat__ = "restructuredtext en" 14 15# --------------------------------------------------------------------------- 16# Imports 17# --------------------------------------------------------------------------- 18 19import logging 20 21from grizzled.exception import ExceptionWithMessage 22 23# --------------------------------------------------------------------------- 24# Exports 25# --------------------------------------------------------------------------- 26 27__all__ = ['ReadOnly', 'ReadOnlyObjectError'] 28 29# --------------------------------------------------------------------------- 30# Constants 31# --------------------------------------------------------------------------- 32 33# --------------------------------------------------------------------------- 34# Logging 35# --------------------------------------------------------------------------- 36 37log = logging.getLogger('grizzled.misc') 38 39# --------------------------------------------------------------------------- 40# Public classes 41# --------------------------------------------------------------------------- 42 43class ReadOnlyObjectError(ExceptionWithMessage): 44 """ 45 Thrown by ``ReadOnly`` to indicate an attempt to set a field. 46 47 :IVariables: 48 field_name : str 49 name of the read-only field that could not be set 50 51 message : str 52 message to associated with the exception 53 """ 54 def __init__(self, field_name, message): 55 ExceptionWithMessage.__init__(self, message) 56 self.field_name = field_name 57 58class ReadOnly(object): 59 """ 60 A ``ReadOnly`` object wraps another object and prevents all the contained 61 object's fields from being written. Example use: 62 63 .. python:: 64 65 from grizzled.misc import ReadOnly 66 from grizzled.config import Configuration 67 68 config = Configuration() 69 config.read('/path/to/some/file') 70 roConfig = ReadOnly(config) 71 72 Any attempt to set fields within ``roConfig`` will cause a 73 ``ReadOnlyObjectError`` to be raised. 74 75 The ``__class__`` member of the instantiate ``ReadOnly`` class will be the 76 class of the contained object, rather than ``ReadOnly`` 77 (``Configuration`` in the example). Similarly, the ``isinstance()`` 78 built-in function will compare against the contained object's class. 79 However, the ``type()`` built-in will return the ``ReadOnly`` class 80 object. 81 """ 82 def __init__(self, wrapped): 83 """ 84 Create a new ``ReadOnly`` object that wraps the ``wrapped`` object 85 and enforces read-only access to it. 86 87 :Parameters: 88 wrapped : object 89 the object to wrap 90 """ 91 self.wrapped = wrapped 92 93 def __getattribute__(self, thing): 94 wrapped = object.__getattribute__(self, 'wrapped') 95 result = None 96 if thing == 'wrapped': 97 result = wrapped 98 else: 99 result = getattr(wrapped, thing) 100 101 return result 102 103 def __setattr__(self, thing, value): 104 if thing == 'wrapped': 105 object.__setattr__(self, thing, value) 106 else: 107 raise ReadOnlyObjectError(thing, 108 'Attempt to access field "%s" of ' 109 'read-only %s object' % 110 (thing, self.wrapped.__class__.__name__)) 111 112# --------------------------------------------------------------------------- 113# Public functions 114# --------------------------------------------------------------------------- 115 116# backward compatibality 117from grizzled.text import str2bool 118 119def bitcount(num): 120 """ 121 Count the number of bits in a numeric (integer or long) value. This 122 method is adapted from the Hamming Weight algorithm, described (among 123 other places) at http://en.wikipedia.org/wiki/Hamming_weight 124 125 Works for up to 64 bits. 126 127 :Parameters: 128 num : int 129 The numeric value 130 131 :rtype: int 132 :return: The number of 1 bits in the binary representation of ``num`` 133 """ 134 # Put count of each 2 bits into those 2 bits. 135 num = num - ((num >> 1) & 0x5555555555555555) 136 137 # Put count of each 4 bits into those 4 bits. 138 num = (num & 0x3333333333333333) + ((num >> 2) & 0x3333333333333333) 139 140 # Put count of each 8 bits into those 8 bits. 141 num = (num + (num >> 4)) & 0x0f0f0f0f0f0f0f0f 142 143 # Left-most bits. 144 return int((num * 0x0101010101010101) >> 56) 145 146 147