Package grizzled :: Module system
[hide private]
[frames] | no frames]

Source Code for Module grizzled.system

  1  # NOTE: Documentation is intended to be processed by epydoc and contains 
  2  # epydoc markup. 
  3   
  4  """ 
  5  Overview 
  6  ======== 
  7   
  8  The ``grizzled.system`` module contains some functions and classes that 
  9  provide information about the Python system (the Python runtime, the language, 
 10  etc.). It is a conceptual extension of the standard Python ``sys`` module. 
 11  """ 
 12   
 13  from __future__ import absolute_import 
 14   
 15  __docformat__ = "restructuredtext en" 
 16   
 17  # --------------------------------------------------------------------------- 
 18  # Imports 
 19  # --------------------------------------------------------------------------- 
 20   
 21  import sys as _sys 
 22  import logging 
 23  import re 
 24   
 25  # --------------------------------------------------------------------------- 
 26  # Exports 
 27  # --------------------------------------------------------------------------- 
 28   
 29  __all__ = ['python_version', 'python_version_string', 'ensure_version', 
 30             'split_python_version', 'class_for_name'] 
 31   
 32  # --------------------------------------------------------------------------- 
 33  # Constants 
 34  # --------------------------------------------------------------------------- 
 35   
 36  RELEASE_LEVEL_RE = re.compile(r'([0-9]+)(.[0-9]+)?') 
 37  RELEASE_LEVELS = {'a' : 0xa, 'b' : 0xb, 'c' : 0xc, 'f' : 0xf} 
 38  RELEASE_LEVEL_NAMES = {0xa : 'alpha', 
 39                         0xb : 'beta', 
 40                         0xc : 'candidate', 
 41                         0xf : 'final'} 
 42   
 43  # --------------------------------------------------------------------------- 
 44  # Logging 
 45  # --------------------------------------------------------------------------- 
 46   
 47  log = logging.getLogger('grizzled.system') 
 48   
 49  # --------------------------------------------------------------------------- 
 50  # Public classes 
 51  # --------------------------------------------------------------------------- 
 52   
 53  # --------------------------------------------------------------------------- 
 54  # Public functions 
 55  # --------------------------------------------------------------------------- 
 56   
57 -def python_version(version):
58 """ 59 Convert a Python string version (e.g., "2.5.1", "1.3", "2.6a3") to a 60 numeric version that can meaningfully be compared with the standard 61 ``sys`` module's ``sys.hexversion`` value. 62 63 For example, here's the usual way to ensure that your program is running 64 under Python 2.5.1 or better: 65 66 .. python:: 67 68 import sys 69 70 if sys.hexversion < 0x020501f0: 71 raise RuntimeError, 'This program requires Python 2.5.1 or better' 72 73 Here's how you'd use ``python_version()`` to do the same thing (in an 74 arguably more readable way): 75 76 .. python:: 77 78 import sys 79 from grizzled.sys import python_version 80 81 if sys.hexversion < python_version("2.5.1"): 82 raise RuntimeError, 'This program requires Python 2.5.1 or better' 83 84 :Parameters: 85 version : str 86 string Python version to convert to binary 87 88 :rtype: int 89 :return: corresponding integer Python version 90 91 :raise ValueError: ``version`` isn't of the form "x", or "x.y" or 92 "x.y.z" 93 """ 94 err = 'Malformed Python version "%s"' % version 95 96 tokens = version.split('.') 97 if len(tokens) > 3: 98 raise ValueError, err 99 100 major = int(tokens[0]) 101 minor = micro = serial = 0 102 release_level = 'f' 103 104 if len(tokens) > 1: 105 match = RELEASE_LEVEL_RE.match(tokens[1]) 106 if not match: 107 raise ValueError, err 108 109 minor = int(match.group(1)) 110 rl = match.group(2) 111 if rl: 112 release_level = rl[0] 113 serial = int(rl[1:]) 114 115 if len(tokens) > 2: 116 match = RELEASE_LEVEL_RE.match(tokens[2]) 117 if not match: 118 raise ValueError, err 119 120 micro = int(match.group(1)) 121 rl2 = match.group(2) 122 if rl and rl2: 123 raise ValueError, err 124 if rl2: 125 release_level = rl2[0] 126 serial = int(rl2[1:]) 127 128 try: 129 release_level = RELEASE_LEVELS[release_level] 130 except KeyError: 131 raise ValueError, err 132 133 return (major << 24) |\ 134 (minor << 16) |\ 135 (micro << 8) |\ 136 (release_level << 4) |\ 137 serial
138
139 -def split_python_version(version=None):
140 """ 141 Convert a binary Python version string (e.g., ``0x020501f0``) into the 142 same (*major*, *minor*, *micro*, *releaselevel*, *serial*) tuple that is 143 found in ``sys.version_info``. Thus, for an input value of ``0x020501f0``, 144 this function returns the tuple ``(2, 5, 1, 'final', 0)``. 145 146 :Parameters: 147 version : int 148 Python integer version 149 150 :rtype: tuple 151 :return: The (*major*, *minor*, *micro*, *releaselevel*, *serial*) tuple 152 153 :raise ValueError: Bad version number 154 """ 155 major = (version >> 24) & 0x000000ff 156 minor = (version >> 16) & 0x000000ff 157 micro = (version >> 8) & 0x000000ff 158 release_level = (version >> 4) & 0x0000000f 159 serial = version & 0x0000000f 160 161 release_level_string = RELEASE_LEVEL_NAMES.get(release_level, None) 162 if not release_level_string: 163 raise ValueError, \ 164 'Bad release level 0x%x in version 0x%08x' %\ 165 (release_level, version) 166 167 return (major, minor, micro, release_level_string, serial)
168
169 -def python_version_string(version=None):
170 """ 171 Convert a numeric Python version (such as ``sys.hexversion``) to a 172 printable string. 173 174 :Parameters: 175 version : int 176 Python integer version 177 178 :rtype: str 179 :return: The stringified version 180 """ 181 major, minor, micro, release_level, serial = split_python_version(version) 182 s = '%d.%d' % (major, minor) 183 if micro > 0: 184 s += '.%d' % micro 185 186 if release_level != 'final': 187 s += release_level[0] 188 s += '%s' % serial 189 190 return s
191
192 -def ensure_version(min_version):
193 """ 194 Raise a ``RuntimeError`` if the current Python version isn't at least 195 ``min_version``. ``min_version`` may be an ``int`` (e.g., ``0x020500f0``) 196 or a string (e.g., "2.5.0"). 197 198 :Parameters: 199 min_version : str or int 200 minimum version, as a number or string 201 202 :raise TypeError: ``min_version`` isn't a string or an integer 203 :raise ValueError: ``min_version`` is a bad Python string version 204 :raise RuntimeError: Python version is too old 205 """ 206 if type(min_version) == str: 207 min_version = python_version(min_version) 208 elif type(min_version) == int: 209 pass 210 else: 211 raise TypeError, \ 212 'version %s is not a string or an integer' % min_version 213 214 if _sys.hexversion < min_version: 215 raise RuntimeError, \ 216 'This program requires Python version "%s" or better, but ' \ 217 'the current Python version is "%s".' %\ 218 (python_version_string(min_version), 219 python_version_string(sys.hexversion))
220 221
222 -def class_for_name(class_name):
223 """ 224 Given fully-qualified class name, load and return the class object. A 225 fully-qualified class name contains the module and package, in addition to 226 the simple class name (e.g., ``grizzled.config.Configuration``). 227 228 :Parameters: 229 class_name : str 230 fully-qualified class name 231 232 :rtype: class 233 :return: the class object 234 235 :raise NameError: Class not found 236 """ 237 tokens = class_name.split('.') 238 if len(tokens) > 1: 239 package = '.'.join(tokens[:-1]) 240 class_name = tokens[-1] 241 exec 'from %s import %s' % (package, class_name) 242 243 return eval(class_name)
244