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