"Fossies" - the Fresh Open Source Software Archive

Member "relax-5.0.0/lib/compat.py" (4 Dec 2019, 14418 Bytes) of package /linux/privat/relax-5.0.0.src.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "compat.py" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.1.3_vs_5.0.0.

    1 ###############################################################################
    2 #                                                                             #
    3 # Copyright (C) 2012-2014,2019 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 itertools
   58 import os
   59 import platform
   60 import sys
   61 import threading
   62 
   63 
   64 # The operating system.
   65 SYSTEM = platform.uname()[0]
   66 if SYSTEM == 'Microsoft':
   67     SYSTEM == 'Windows'
   68 
   69 # The Python version.
   70 PY_VERSION = sys.version_info[0]
   71 
   72 
   73 # Special Python version specific imports.  These will be imported from here from the rest of relax.
   74 ####################################################################################################
   75 
   76 # The built-in module.
   77 if PY_VERSION == 2:
   78     import __builtin__ as builtins
   79 else:
   80     import builtins
   81 
   82 # The queue module.
   83 if PY_VERSION == 2:
   84     import Queue as queue
   85 else:
   86     import queue
   87 
   88 # The queue.Queue class
   89 if PY_VERSION == 2:
   90     from Queue import Queue as Queue2
   91 else:
   92     from queue import Queue as Queue3
   93     Queue2 = Queue3
   94 
   95 # The StringIO class.
   96 if PY_VERSION == 2:
   97     from cStringIO import StringIO
   98 elif io_module:
   99     from io import StringIO
  100 else:
  101     StringIO = None
  102 
  103 # The unit test TextTestResult class.
  104 try:
  105     from unittest import TextTestResult    # Python 2.7 and above.
  106 except ImportError:
  107     from unittest import _TextTestResult as TextTestResult    # Python 2.6 and below.
  108 
  109 # The pickle package.
  110 if PY_VERSION == 2:
  111     import cPickle as pickle
  112 else:
  113     import pickle
  114 
  115 # Numpy.
  116 import numpy
  117 try:
  118     numpy.linalg.norm(numpy.ones((3, 3)), axis=1)
  119     numpy_norm_axis = True
  120 except:
  121     numpy_norm_axis = False
  122 
  123 # Linux distribution information.
  124 try:
  125     from platform import linux_distribution
  126 except ImportError:
  127     try:
  128         from distro import linux_distribution
  129     except ImportError:
  130         def linux_distribution(): return [None]
  131 
  132 
  133 def bz2_open(file, mode='r'):
  134     """Abstract the numerous ways BZ2 files are handled in Python.
  135 
  136     @param file:    The file path to open.
  137     @type file:     str
  138     @keyword mode:  The mode to open the file with.  Only the values of 'r' and 'w' for reading and writing respectively are supported.
  139     @type mode:     str
  140     @return:        The bzip2 file object.
  141     @rtype:         file object
  142     """
  143 
  144     # Check the mode.
  145     if mode not in ['r', 'w']:
  146         raise RelaxError("The mode '%s' must be one or 'r' or 'w'." % mode)
  147 
  148     # Check if the bz2 module exists.
  149     if not bz2_module:
  150         if mode == 'r':
  151             raise RelaxError("Cannot open the file %s, try uncompressing first.  %s." % (file, bz2_module_message))
  152         else:
  153             raise RelaxError("Cannot create bzip2 file %s, the bz2 Python module cannot be found." % file)
  154 
  155     # Open the file for reading.
  156     if mode == 'r':
  157         # Python 3.3 text mode.
  158         if sys.version_info[0] == 3 and sys.version_info[1] >= 3:
  159             file_obj = bz2.open(file, 't')
  160 
  161         # Python 3.0, 3.1 and 3.2 text mode.
  162         elif sys.version_info[0] == 3 and sys.version_info[1] < 3:
  163             file_obj = io.TextIOWrapper(Bzip2Fixed(file, 'r'))
  164 
  165         # Python 2 text mode.
  166         else:
  167             file_obj = bz2.BZ2File(file, 'r')
  168 
  169     # Open the file for writing.
  170     elif mode == 'w':
  171         # Python 3.3 text mode.
  172         if sys.version_info[0] == 3 and sys.version_info[1] >= 3:
  173             file_obj = bz2.open(file, 'wt')
  174 
  175         # Python 3.0, 3.1 and 3.2 text mode.
  176         elif sys.version_info[0] == 3 and sys.version_info[1] < 3:
  177             file_obj = io.TextIOWrapper(Bzip2Fixed(file, 'w'))
  178 
  179         # Python 2 text mode.
  180         else:
  181             file_obj = bz2.BZ2File(file, 'w')
  182 
  183     # Return the file object.
  184     return file_obj
  185 
  186 
  187 def gz_open(file, mode='r'):
  188     """Abstract the numerous ways gzipped files are handled in Python.
  189 
  190     @param file:    The file path to open.
  191     @type file:     str
  192     @keyword mode:  The mode to open the file with.  Only the values of 'r' and 'w' for reading and writing respectively are supported.
  193     @type mode:     str
  194     @return:        The gzipped file object.
  195     @rtype:         file object
  196     """
  197 
  198     # Check the mode.
  199     if mode not in ['r', 'w']:
  200         raise RelaxError("The mode '%s' must be one or 'r' or 'w'." % mode)
  201 
  202     # Check if the bz2 module exists.
  203     if not gzip_module:
  204         if mode == 'r':
  205             raise RelaxError("Cannot open the file %s, try uncompressing first.  %s." % (file, gzip_module_message))
  206         else:
  207             raise RelaxError("Cannot create gzipped file %s, the bz2 Python module cannot be found." % file)
  208 
  209     # Open the file for reading.
  210     if mode == 'r':
  211         # Python 3.3 text mode.
  212         if sys.version_info[0] == 3 and sys.version_info[1] >= 3:
  213             file_obj = gzip.open(file, 'rt')
  214 
  215         # Python 3.0, 3.1 and 3.2 text mode.
  216         elif sys.version_info[0] == 3 and sys.version_info[1] < 3:
  217             file_obj = io.TextIOWrapper(GzipFixed(file, 'r'))
  218 
  219         # Python 2 text mode.
  220         else:
  221             file_obj = gzip.GzipFile(file, 'r')
  222 
  223     # Open the file for writing.
  224     elif mode == 'w':
  225         # Python 3.3 text mode.
  226         if sys.version_info[0] == 3 and sys.version_info[1] >= 3:
  227             file_obj = gzip.open(file, 'wt')
  228 
  229         # Python 3.0, 3.1 and 3.2 text mode.
  230         elif sys.version_info[0] == 3 and sys.version_info[1] < 3:
  231             file_obj = io.TextIOWrapper(GzipFixed(file, 'w'))
  232 
  233             # Python 2 text mode.
  234         else:
  235             file_obj = gzip.GzipFile(file, 'w')
  236 
  237     # Return the file object.
  238     return file_obj
  239 
  240 
  241 def from_iterable(items):
  242     """Implementation of the itertools.chain.from_iterable() function for all Python versions.
  243 
  244     @param items:   The normal argument for itertools.chain.from_iterable().
  245     @type items:    list
  246     @return:        The items of the list.
  247     @rtype:         unknown
  248     """
  249 
  250     # Default to the normal function.
  251     if hasattr(itertools.chain, 'from_iterable'):
  252         return itertools.chain.from_iterable(items)
  253 
  254     # Reimplement the function for earlier Python versions.
  255     return from_iterable_pre_2_6(items)
  256 
  257 
  258 def from_iterable_pre_2_6(items):
  259     """Replacement itertools.chain.from_iterable() function for Python < 2.6.
  260 
  261     @param items:   The normal argument for itertools.chain.from_iterable().
  262     @type items:    list
  263     @return:        The elements
  264     @rtype:         unknown
  265     """
  266 
  267     for item in items:
  268         for element in item:
  269             yield element
  270 
  271 
  272 def norm(x, ord=None, axis=None):
  273     """Replacement numpy.linalg.norm() function to handle the axis argument for old numpy.
  274 
  275     @param x:       Input array.  If `axis` is None, `x` must be 1-D or 2-D.
  276     @type x:        array_like
  277     @keyword ord:   Order of the norm (see table under ``Notes``). inf means numpy's `inf` object.
  278     @type ord:      {non-zero int, inf, -inf, 'fro'}, optional
  279     @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.
  280     @type axis:     {int, 2-tuple of ints, None}, optional
  281     """
  282 
  283     # No axis argument given.
  284     if axis == None:
  285         return numpy.linalg.norm(x, ord=ord)
  286 
  287     # The axis argument exists.
  288     if numpy_norm_axis:
  289         return numpy.linalg.norm(x, ord=ord, axis=axis)
  290 
  291     # Support for older version (this is much slower).
  292     return numpy.apply_along_axis(numpy.linalg.norm, axis, x)
  293 
  294 
  295 
  296 class Bzip2Fixed(BZ2File):
  297     """Incredibly nasty hack for bzip2 files support in Python 3.0, 3.1 and 3.2."""
  298 
  299     def flush(self):
  300         pass
  301 
  302     def read1(self, n):
  303         return self.read(n)
  304 
  305     def readable(self):
  306         return True
  307 
  308     def seekable(self):
  309         return True
  310 
  311     def writable(self):
  312         return True
  313 
  314 
  315 
  316 class GzipFixed(gzip.GzipFile):
  317     """Incredibly nasty hack for gzipped files support in Python 3.0, 3.1 and 3.2."""
  318 
  319     closed = False
  320 
  321     def read1(self, n):
  322         return self.read(n)
  323 
  324     def readable(self):
  325         return True
  326 
  327     def seekable(self):
  328         return True
  329 
  330     def writable(self):
  331         return True
  332 
  333 
  334 
  335 class TaskQueue(Queue2):
  336     """Python 2.4 and earlier Queuing class replacement.
  337 
  338     This code comes from http://code.activestate.com/recipes/475160/ and is part of the Python sources from 2.5 onwards.
  339     """
  340 
  341     def __init__(self):
  342         Queue2.__init__(self)
  343         self.all_tasks_done = threading.Condition(self.mutex)
  344         self.unfinished_tasks = 0
  345 
  346     def _put(self, item):
  347         Queue2._put(self, item)
  348         self.unfinished_tasks += 1
  349 
  350     def task_done(self):
  351         """Indicate that a formerly enqueued task is complete.
  352 
  353         Used by Queue consumer threads.  For each get() used to fetch a task,
  354         a subsequent call to task_done() tells the queue that the processing
  355         on the task is complete.
  356 
  357         If a join() is currently blocking, it will resume when all items
  358         have been processed (meaning that a task_done() call was received
  359         for every item that had been put() into the queue).
  360 
  361         Raises a ValueError if called more times than there were items
  362         placed in the queue.
  363         """
  364         self.all_tasks_done.acquire()
  365         try:
  366             unfinished = self.unfinished_tasks - 1
  367             if unfinished <= 0:
  368                 if unfinished < 0:
  369                     raise ValueError('task_done() called too many times')
  370                 self.all_tasks_done.notifyAll()
  371             self.unfinished_tasks = unfinished
  372         finally:
  373             self.all_tasks_done.release()
  374 
  375     def join(self):
  376         """Blocks until all items in the Queue have been gotten and processed.
  377 
  378         The count of unfinished tasks goes up whenever an item is added to the
  379         queue. The count goes down whenever a consumer thread calls task_done()
  380         to indicate the item was retrieved and all work on it is complete.
  381 
  382         When the count of unfinished tasks drops to zero, join() unblocks.
  383         """
  384         self.all_tasks_done.acquire()
  385         try:
  386             while self.unfinished_tasks:
  387                 self.all_tasks_done.wait()
  388         finally:
  389             self.all_tasks_done.release()
  390 
  391 
  392 # Alias the correct Queue.
  393 if PY_VERSION == 2 and sys.version_info[1] <= 4:
  394     Queue = TaskQueue    # Alias the TaskQueue for Python 2.4 and earlier.
  395 elif PY_VERSION == 2:
  396     Queue = Queue2
  397 else:
  398     Queue = Queue3
  399 
  400 
  401 # Python 2 hacks.
  402 if PY_VERSION == 2:
  403     # Switch all range() calls to xrange() for increased speed and memory reduction.
  404     # This should work as all range() usage for Python 3 in relax must match the old xrange() usage.
  405     #builtins.range = builtins.xrange
  406 
  407     # The os.devnull object for Python 2.3 and earlier.
  408     if sys.version_info[1] <= 3:
  409         if SYSTEM == 'Linux':
  410             os.devnull = '/dev/null'
  411         elif SYSTEM == 'Windows':
  412             os.devnull = 'nul'
  413         elif SYSTEM == 'Darwin':
  414             os.devnull = 'Dev:Null'
  415         else:
  416             os.devnull = None
  417 
  418     # The unicode conversion function - essential for the GUI in Python 2.
  419     unicode = builtins.unicode
  420 
  421     # Unicode string handling.
  422     from codecs import unicode_escape_decode
  423     def u(text):
  424         """Create a unicode string for Python 2.
  425 
  426         @param text:    The text to convert.
  427         @type text:     str
  428         @return:        The text converted to unicode.
  429         @rtype:         unicode
  430         """
  431 
  432         return unicode_escape_decode(text)[0]
  433 
  434 
  435 # Python 3 work-arounds.
  436 if PY_VERSION == 3:
  437     # The unicode conversion function - essential for the GUI in Python 2.
  438     unicode = builtins.str
  439 
  440     # Unicode string handling.
  441     def u(text):
  442         """Create a unicode string for Python 3.
  443 
  444         @param text:    The text to convert.
  445         @type text:     str
  446         @return:        The unmodified text, as all strings in Python 3 are unicode and the unicode type does not exist.
  447         @rtype:         str
  448         """
  449 
  450         return text