Package lib :: Module compat
[hide private]
[frames] | no frames]

Source Code for Module lib.compat

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2012-2014 Edward d'Auvergne                                   # 
  4  #                                                                             # 
  5  # This file is part of the program relax (http://www.nmr-relax.com).          # 
  6  #                                                                             # 
  7  # This program is free software: you can redistribute it and/or modify        # 
  8  # it under the terms of the GNU General Public License as published by        # 
  9  # the Free Software Foundation, either version 3 of the License, or           # 
 10  # (at your option) any later version.                                         # 
 11  #                                                                             # 
 12  # This program is distributed in the hope that it will be useful,             # 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 15  # GNU General Public License for more details.                                # 
 16  #                                                                             # 
 17  # You should have received a copy of the GNU General Public License           # 
 18  # along with this program.  If not, see <http://www.gnu.org/licenses/>.       # 
 19  #                                                                             # 
 20  ############################################################################### 
 21   
 22  # Module docstring. 
 23  """Temporary module for allowing relax to support both Python 2 and 3.""" 
 24   
 25  # The platform script message. 
 26  try: 
 27      import platform 
 28  except ImportError: 
 29      print("The platform module cannot be imported.  For Python <= 2.2, try copying the platform.py file from http://hg.python.org/cpython/file/2.3/Lib/platform.py into your lib/pythonX.X/ directory.") 
 30      raise 
 31   
 32  # Python module imports. 
 33  try: 
 34      import bz2 
 35      from bz2 import BZ2File 
 36      bz2_module = True 
 37  except ImportError: 
 38      BZ2File = object 
 39      bz2_module = False 
 40      message = sys.exc_info()[1] 
 41      bz2_module_message = message.args[0] 
 42  try: 
 43      import gzip 
 44      gzip_module = True 
 45  except ImportError: 
 46      gzip = object 
 47      gzip_module = False 
 48      message = sys.exc_info()[1] 
 49      gzip_module_message = message.args[0] 
 50  try: 
 51      import io 
 52      io_module = True 
 53      from io import IOBase 
 54  except ImportError: 
 55      io_module = False 
 56      IOBase = None 
 57  import os 
 58  import platform 
 59  import sys 
 60  import threading 
 61   
 62   
 63  # The operating system. 
 64  SYSTEM = platform.uname()[0] 
 65  if SYSTEM == 'Microsoft': 
 66      SYSTEM == 'Windows' 
 67   
 68  # The Python version. 
 69  PY_VERSION = sys.version_info[0] 
 70   
 71   
 72  # Special Python version specific imports.  These will be imported from here from the rest of relax. 
 73  #################################################################################################### 
 74   
 75  # The built-in module. 
 76  if PY_VERSION == 2: 
 77      import __builtin__ as builtins 
 78  else: 
 79      import builtins 
 80   
 81  # The queue module. 
 82  if PY_VERSION == 2: 
 83      import Queue as queue 
 84  else: 
 85      import queue 
 86   
 87  # The queue.Queue class 
 88  if PY_VERSION == 2: 
 89      from Queue import Queue as Queue2 
 90  else: 
 91      from queue import Queue as Queue3 
 92      Queue2 = Queue3 
 93   
 94  # The StringIO class. 
 95  if PY_VERSION == 2: 
 96      from cStringIO import StringIO 
 97  elif io_module: 
 98      from io import StringIO 
 99  else: 
100      StringIO = None 
101   
102  # The unit test TextTestResult class. 
103  try: 
104      from unittest import TextTestResult    # Python 2.7 and above. 
105  except ImportError: 
106      from unittest import _TextTestResult as TextTestResult    # Python 2.6 and below. 
107   
108  # The pickle package. 
109  if PY_VERSION == 2: 
110      import cPickle as pickle 
111  else: 
112      import pickle 
113   
114  # Numpy. 
115  import numpy 
116  try: 
117      numpy.linalg.norm(numpy.ones((3, 3)), axis=1) 
118      numpy_norm_axis = True 
119  except: 
120      numpy_norm_axis = False 
121   
122   
123 -def bz2_open(file, mode='r'):
124 """Abstract the numerous ways BZ2 files are handled in Python. 125 126 @param file: The file path to open. 127 @type file: str 128 @keyword mode: The mode to open the file with. Only the values of 'r' and 'w' for reading and writing respectively are supported. 129 @type mode: str 130 @return: The bzip2 file object. 131 @rtype: file object 132 """ 133 134 # Check the mode. 135 if mode not in ['r', 'w']: 136 raise RelaxError("The mode '%s' must be one or 'r' or 'w'." % mode) 137 138 # Check if the bz2 module exists. 139 if not bz2_module: 140 if mode == 'r': 141 raise RelaxError("Cannot open the file %s, try uncompressing first. %s." % (file, bz2_module_message)) 142 else: 143 raise RelaxError("Cannot create bzip2 file %s, the bz2 Python module cannot be found." % file) 144 145 # Open the file for reading. 146 if mode == 'r': 147 # Python 3.3 text mode. 148 if sys.version_info[0] == 3 and sys.version_info[1] >= 3: 149 file_obj = bz2.open(file, 't') 150 151 # Python 3.0, 3.1 and 3.2 text mode. 152 elif sys.version_info[0] == 3 and sys.version_info[1] < 3: 153 file_obj = io.TextIOWrapper(Bzip2Fixed(file, 'r')) 154 155 # Python 2 text mode. 156 else: 157 file_obj = bz2.BZ2File(file, 'r') 158 159 # Open the file for writing. 160 elif mode == 'w': 161 # Python 3.3 text mode. 162 if sys.version_info[0] == 3 and sys.version_info[1] >= 3: 163 file_obj = bz2.open(file, 'wt') 164 165 # Python 3.0, 3.1 and 3.2 text mode. 166 elif sys.version_info[0] == 3 and sys.version_info[1] < 3: 167 file_obj = io.TextIOWrapper(Bzip2Fixed(file, 'w')) 168 169 # Python 2 text mode. 170 else: 171 file_obj = bz2.BZ2File(file, 'w') 172 173 # Return the file object. 174 return file_obj
175 176
177 -def gz_open(file, mode='r'):
178 """Abstract the numerous ways gzipped files are handled in Python. 179 180 @param file: The file path to open. 181 @type file: str 182 @keyword mode: The mode to open the file with. Only the values of 'r' and 'w' for reading and writing respectively are supported. 183 @type mode: str 184 @return: The gzipped file object. 185 @rtype: file object 186 """ 187 188 # Check the mode. 189 if mode not in ['r', 'w']: 190 raise RelaxError("The mode '%s' must be one or 'r' or 'w'." % mode) 191 192 # Check if the bz2 module exists. 193 if not gzip_module: 194 if mode == 'r': 195 raise RelaxError("Cannot open the file %s, try uncompressing first. %s." % (file, gzip_module_message)) 196 else: 197 raise RelaxError("Cannot create gzipped file %s, the bz2 Python module cannot be found." % file) 198 199 # Open the file for reading. 200 if mode == 'r': 201 # Python 3.3 text mode. 202 if sys.version_info[0] == 3 and sys.version_info[1] >= 3: 203 file_obj = gzip.open(file, 'rt') 204 205 # Python 3.0, 3.1 and 3.2 text mode. 206 elif sys.version_info[0] == 3 and sys.version_info[1] < 3: 207 file_obj = io.TextIOWrapper(GzipFixed(file, 'r')) 208 209 # Python 2 text mode. 210 else: 211 file_obj = gzip.GzipFile(file, 'r') 212 213 # Open the file for writing. 214 elif mode == 'w': 215 # Python 3.3 text mode. 216 if sys.version_info[0] == 3 and sys.version_info[1] >= 3: 217 file_obj = gzip.open(file, 'wt') 218 219 # Python 3.0, 3.1 and 3.2 text mode. 220 elif sys.version_info[0] == 3 and sys.version_info[1] < 3: 221 file_obj = io.TextIOWrapper(GzipFixed(file, 'w')) 222 223 # Python 2 text mode. 224 else: 225 file_obj = gzip.GzipFile(file, 'w') 226 227 # Return the file object. 228 return file_obj
229 230
231 -def norm(x, ord=None, axis=None):
232 """Replacement numpy.linalg.norm() function to handle the axis argument for old numpy. 233 @param x: Input array. If `axis` is None, `x` must be 1-D or 2-D. 234 @type x: array_like 235 @keyword ord: Order of the norm (see table under ``Notes``). inf means numpy's `inf` object. 236 @type ord: {non-zero int, inf, -inf, 'fro'}, optional 237 @keyword axis: If `axis` is an integer, it specifies the axis of `x` along which to compute the vector norms. If `axis` is a 2-tuple, it specifies the axes that hold 2-D matrices, and the matrix norms of these matrices are computed. If `axis` is None then either a vector norm (when `x` is 1-D) or a matrix norm (when `x` is 2-D) is returned. 238 @type axis: {int, 2-tuple of ints, None}, optional 239 """ 240 241 # No axis argument given. 242 if axis == None: 243 return numpy.linalg.norm(x, ord=ord) 244 245 # The axis argument exists. 246 if numpy_norm_axis: 247 return numpy.linalg.norm(x, ord=ord, axis=axis) 248 249 # Support for older version (this is much slower). 250 return numpy.apply_along_axis(numpy.linalg.norm, axis, x)
251 252 253
254 -class Bzip2Fixed(BZ2File):
255 """Incredibly nasty hack for bzip2 files support in Python 3.0, 3.1 and 3.2.""" 256
257 - def flush(self):
258 pass
259
260 - def read1(self, n):
261 return self.read(n)
262
263 - def readable(self):
264 return True
265
266 - def seekable(self):
267 return True
268
269 - def writable(self):
270 return True
271 272 273
274 -class GzipFixed(gzip.GzipFile):
275 """Incredibly nasty hack for gzipped files support in Python 3.0, 3.1 and 3.2.""" 276 277 closed = False 278
279 - def read1(self, n):
280 return self.read(n)
281
282 - def readable(self):
283 return True
284
285 - def seekable(self):
286 return True
287
288 - def writable(self):
289 return True
290 291 292
293 -class TaskQueue(Queue2):
294 """Python 2.4 and earlier Queuing class replacement. 295 296 This code comes from http://code.activestate.com/recipes/475160/ and is part of the Python sources from 2.5 onwards. 297 """ 298
299 - def __init__(self):
300 Queue2.__init__(self) 301 self.all_tasks_done = threading.Condition(self.mutex) 302 self.unfinished_tasks = 0
303
304 - def _put(self, item):
305 Queue2._put(self, item) 306 self.unfinished_tasks += 1
307
308 - def task_done(self):
309 """Indicate that a formerly enqueued task is complete. 310 311 Used by Queue consumer threads. For each get() used to fetch a task, 312 a subsequent call to task_done() tells the queue that the processing 313 on the task is complete. 314 315 If a join() is currently blocking, it will resume when all items 316 have been processed (meaning that a task_done() call was received 317 for every item that had been put() into the queue). 318 319 Raises a ValueError if called more times than there were items 320 placed in the queue. 321 """ 322 self.all_tasks_done.acquire() 323 try: 324 unfinished = self.unfinished_tasks - 1 325 if unfinished <= 0: 326 if unfinished < 0: 327 raise ValueError('task_done() called too many times') 328 self.all_tasks_done.notifyAll() 329 self.unfinished_tasks = unfinished 330 finally: 331 self.all_tasks_done.release()
332
333 - def join(self):
334 """Blocks until all items in the Queue have been gotten and processed. 335 336 The count of unfinished tasks goes up whenever an item is added to the 337 queue. The count goes down whenever a consumer thread calls task_done() 338 to indicate the item was retrieved and all work on it is complete. 339 340 When the count of unfinished tasks drops to zero, join() unblocks. 341 """ 342 self.all_tasks_done.acquire() 343 try: 344 while self.unfinished_tasks: 345 self.all_tasks_done.wait() 346 finally: 347 self.all_tasks_done.release()
348 349 350 # Alias the correct Queue. 351 if PY_VERSION == 2 and sys.version_info[1] <= 4: 352 Queue = TaskQueue # Alias the TaskQueue for Python 2.4 and earlier. 353 elif PY_VERSION == 2: 354 Queue = Queue2 355 else: 356 Queue = Queue3 357 358 359 # Python 2 hacks. 360 if PY_VERSION == 2: 361 # Switch all range() calls to xrange() for increased speed and memory reduction. 362 # This should work as all range() usage for Python 3 in relax must match the old xrange() usage. 363 #builtins.range = builtins.xrange 364 365 # The os.devnull object for Python 2.3 and earlier. 366 if sys.version_info[1] <= 3: 367 if SYSTEM == 'Linux': 368 os.devnull = '/dev/null' 369 elif SYSTEM == 'Windows': 370 os.devnull = 'nul' 371 elif SYSTEM == 'Darwin': 372 os.devnull = 'Dev:Null' 373 else: 374 os.devnull = None 375 376 # The unicode conversion function - essential for the GUI in Python 2. 377 unicode = builtins.unicode 378 379 # Unicode string handling. 380 from codecs import unicode_escape_decode
381 - def u(text):
382 """Create a unicode string for Python 2. 383 384 @param text: The text to convert. 385 @type text: str 386 @return: The text converted to unicode. 387 @rtype: unicode 388 """ 389 390 return unicode_escape_decode(text)[0]
391 392 393 # Python 3 work-arounds. 394 if PY_VERSION == 3: 395 # The unicode conversion function - essential for the GUI in Python 2. 396 unicode = builtins.str 397 398 # Unicode string handling.
399 - def u(text):
400 """Create a unicode string for Python 3. 401 402 @param text: The text to convert. 403 @type text: str 404 @return: The unmodified text, as all strings in Python 3 are unicode and the unicode type does not exist. 405 @rtype: str 406 """ 407 408 return text
409