Package Bio :: Package _py3k
[hide private]
[frames] | no frames]

Source Code for Package Bio._py3k

  1  # Copyright 2010-2013 by Peter Cock.  All rights reserved. 
  2  # This code is part of the Biopython distribution and governed by its 
  3  # license.  Please see the LICENSE file that should have been included 
  4  # as part of this package. 
  5  """Python 3 compatibility tools (PRIVATE). 
  6   
  7  We used to have lines like this under Python 2 in order to use 
  8  iterator based zip, map and filter (in Python 3 these functions 
  9  are all iterator based):: 
 10   
 11      from future_builtins import zip 
 12   
 13  There is no similar option for range yet, other than:: 
 14   
 15      range = xrange 
 16      input = raw_input 
 17   
 18  or: 
 19   
 20      from __builtin__ import xrange as range 
 21      from __builtin__ import raw_input as input 
 22   
 23  Under Python 3 these imports need to be removed. Also, deliberate 
 24  importing of built in functions like open changes from Python 2:: 
 25   
 26      from __builtin__ import open 
 27   
 28  To do this under Python 3: 
 29   
 30      from builtins import open 
 31   
 32  Instead, we can do this under either Python 2 or 3: 
 33   
 34      from Bio._py3k import open 
 35      from Bio._py3k import zip 
 36   
 37  Once we drop support for Python 2, the whole of Bio._py3k will 
 38  go away. 
 39  """ 
 40   
 41  # From the point of view of pep8 and flake8, there are lots of issues with 
 42  # this file. This line tells flake8 to ignore it for quality assurance: 
 43  # flake8: noqa 
 44   
 45  import sys 
 46   
 47   
 48  if sys.version_info[0] >= 3: 
 49      # Code for Python 3 
 50      from builtins import open, zip, map, filter, range, input 
 51   
 52      import codecs 
 53   
 54      # Lots of our Python 2 code uses isinstance(x, basestring) 
 55      # which after 2to3 becomes isinstance(x, str) 
 56      basestring = str 
 57      unicode = str 
 58   
 59      _bytes_to_string = lambda b: b.decode()  # bytes to unicode string 
 60      _string_to_bytes = lambda s: s.encode()  # unicode string to bytes 
 61   
62 - def _bytes_bytearray_to_str(s):
63 """If s is bytes or bytearray, convert to a unicode string.""" 64 if isinstance(s, (bytes, bytearray)): 65 return s.decode() 66 return s
67
68 - def _as_unicode(s):
69 """Turn byte string or unicode string into a unicode string.""" 70 if isinstance(s, str): 71 return s 72 # Assume it is a bytes string 73 # Note ISO-8859-1 aka Latin-1 preserves first 256 chars 74 return codecs.latin_1_decode(s)[0]
75
76 - def _as_bytes(s):
77 """Turn byte string or unicode string into a bytes string. 78 79 The Python 2 version returns a (byte) string. 80 """ 81 if isinstance(s, bytes): 82 return s 83 # Assume it is a unicode string 84 # Note ISO-8859-1 aka Latin-1 preserves first 256 chars 85 return codecs.latin_1_encode(s)[0]
86 87 _as_string = _as_unicode 88
89 - def _is_int_or_long(i):
90 """Check if the value is an integer. 91 92 Note there are no longs on Python 3. 93 """ 94 return isinstance(i, int)
95 96 import io 97 98 if sys.version_info[:2] <= (3, 3):
99 - def _binary_to_string_handle(handle):
100 """Treat a binary (bytes) handle like a text (unicode) handle.""" 101 # TODO, once drop all of Python 3.0 - 3.3, remove this! 102 # 103 # See also http://bugs.python.org/issue5628 104 # and http://bugs.python.org/issue13541 105 # and http://bugs.python.org/issue13464 which should be fixed in Python 3.3 106 # 107 # However, still have problems under Python 3.3.0, e.g. 108 # 109 # $ python3.3 test_SeqIO_online.py 110 # test_nuccore_X52960 (__main__.EntrezTests) 111 # Bio.Entrez.efetch('nuccore', id='X52960', ...) ... ERROR 112 # test_nucleotide_6273291 (__main__.EntrezTests) 113 # Bio.Entrez.efetch('nucleotide', id='6273291', ...) ... ERROR 114 # test_protein_16130152 (__main__.EntrezTests) 115 # Bio.Entrez.efetch('protein', id='16130152', ...) ... ERROR 116 # test_get_sprot_raw (__main__.ExPASyTests) 117 # Bio.ExPASy.get_sprot_raw("O23729") ... ok 118 # .. 119 # ValueError: I/O operation on closed file. 120 # 121 class EvilHandleHack(object): 122 """Biopython internal class to work around bugs in early versions of Python 3.""" 123 def __init__(self, handle): 124 self._handle = handle 125 try: 126 # If wrapping an online handle, this this is nice to have: 127 self.url = handle.url 128 except AttributeError: 129 pass
130 131 def read(self, length=None): 132 return _as_string(self._handle.read(length)) 133 134 def readline(self): 135 return _as_string(self._handle.readline()) 136 137 def __iter__(self): 138 for line in self._handle: 139 yield _as_string(line) 140 141 def close(self): 142 return self._handle.close() 143 144 def seek(self, pos): 145 return self._handle.seek(pos) 146 147 def tell(self): 148 return self._handle.tell() 149 150 return EvilHandleHack(handle) 151 else: 152 # Python 3.4 onwards, the standard library wrappers should work:
153 - def _binary_to_string_handle(handle):
154 """Treat a binary (bytes) handle like a text (unicode) handle.""" 155 wrapped = io.TextIOWrapper(io.BufferedReader(handle)) 156 try: 157 # If wrapping an online handle, this this is nice to have: 158 wrapped.url = handle.url 159 except AttributeError: 160 pass 161 return wrapped
162 163 # This is to avoid the deprecation warning from open(filename, "rU") 164 _universal_read_mode = "r" # text mode does universal new lines 165 166 # On Python 3, this will be a unicode StringIO 167 from io import StringIO 168 169 # On Python 3 urllib, urllib2, and urlparse were merged: 170 from urllib.request import urlopen, Request, urlretrieve, urlparse, urlcleanup 171 from urllib.parse import urlencode, quote 172 from urllib.error import HTTPError 173 174 else: 175 # Python 2 code 176 from __builtin__ import open, basestring, unicode 177 178 # Import Python3 like iterator functions: 179 from future_builtins import zip, map, filter 180 from __builtin__ import xrange as range 181 from __builtin__ import raw_input as input 182 183 _bytes_to_string = lambda b: b # bytes to string, i.e. do nothing 184 _string_to_bytes = lambda s: str(s) # str (or unicode) to bytes string 185
186 - def _bytes_bytearray_to_str(s):
187 """If s is bytes or bytearray, convert to a string.""" 188 if isinstance(s, (bytes, bytearray)): 189 return str(s) 190 return s
191
192 - def _as_unicode(s):
193 """Turn a (byte) string or a unicode string into a (byte) string.""" 194 # Will be changed by 2to3 to "isinstance(s, str)" but doesn't matter: 195 if isinstance(s, unicode): 196 return s 197 return s.decode()
198
199 - def _as_bytes(s):
200 """Turn a (byte) string or a unicode string into a (byte) string.""" 201 return str(s)
202 203 _as_string = _as_bytes 204
205 - def _is_int_or_long(i):
206 """Check if the value is an integer or long.""" 207 return isinstance(i, (int, long))
208
209 - def _binary_to_string_handle(handle):
210 """Treat a binary handle like a text handle.""" 211 return handle
212 213 # This private variable is set to "r" on Python 3 for text 214 # mode which include universal readlines mode 215 _universal_read_mode = "rU" 216 217 # On Python 2 this will be a (bytes) string based handle. 218 # Note this doesn't work as it is unicode based: 219 # from io import StringIO 220 try: 221 from cStringIO import StringIO 222 except ImportError: 223 from StringIO import StringIO 224 225 # Under urllib.request on Python 3: 226 from urllib2 import urlopen, Request 227 from urllib import urlretrieve, urlcleanup 228 from urlparse import urlparse 229 230 # Under urllib.parse on Python 3: 231 from urllib import urlencode, quote 232 233 # Under urllib.error on Python 3: 234 from urllib2 import HTTPError 235 236 237 if sys.platform == "win32": 238 # Can't use commands.getoutput on Python 2, Unix only/broken: 239 # http://bugs.python.org/issue15073 240 # Can't use subprocess.getoutput on Python 3, Unix only/broken: 241 # http://bugs.python.org/issue10197
242 - def getoutput(cmd):
243 import subprocess 244 child = subprocess.Popen(cmd, 245 stdin=subprocess.PIPE, 246 stdout=subprocess.PIPE, 247 stderr=subprocess.STDOUT, 248 universal_newlines=True, 249 shell=False) 250 stdout, stderr = child.communicate() 251 # Remove trailing \n to match the Unix function, 252 return stdout.rstrip("\n")
253 elif sys.version_info[0] >= 3: 254 # Use subprocess.getoutput on Python 3, 255 from subprocess import getoutput 256 else: 257 # Use commands.getoutput on Python 2, 258 from commands import getoutput 259