From 07f57cb81b90f42e5130277601c6b2d73a663475 Mon Sep 17 00:00:00 2001 From: David Cain Date: Wed, 9 Jan 2013 16:11:34 -0500 Subject: [PATCH 01/10] Use urlretrieve to smartly download PDB archives Reading the entire contents into memory with urlopen is a bad idea. With large crystal structures, it can result in saving an incomplete .gz archive (raising an Exception on retrieve_pdb_file). Let urllib handle downloading the file instead. --- Bio/PDB/PDBList.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Bio/PDB/PDBList.py b/Bio/PDB/PDBList.py index eff765a32dd..bfa660187df 100644 --- a/Bio/PDB/PDBList.py +++ b/Bio/PDB/PDBList.py @@ -25,7 +25,8 @@ import gzip import os import shutil -from urllib2 import urlopen as _urlopen +import urllib +from urllib2 import urlopen as _urlopen # urllib made too many FTP conn's import warnings from Bio import BiopythonDeprecationWarning @@ -237,8 +238,7 @@ def retrieve_pdb_file(self,pdb_code, obsolete=0, compression=None, # Retrieve the file print "Downloading PDB structure '%s'..." % pdb_code - lines = _urlopen(url).read() - open(filename,'wb').write(lines) + urllib.urlretrieve(url, filename) # Uncompress the file gz = gzip.open(filename, 'rb') From 641be7f1f56a60484db6b5f5a7ef3cdf68f21f0c Mon Sep 17 00:00:00 2001 From: David Cain Date: Wed, 9 Jan 2013 16:21:31 -0500 Subject: [PATCH 02/10] Use 'with' statement for safer file I/O Many of the modified functions may be obsolete at this point, but they're converted to use the more compact, safe 'with' statement. In Python 2, urllib2.urlopen doesn't implement the 'with' statement, so we temporarily use contextlib to force this until transition to Python 3. --- Bio/PDB/PDBList.py | 85 ++++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 45 deletions(-) diff --git a/Bio/PDB/PDBList.py b/Bio/PDB/PDBList.py index bfa660187df..b8f6d763ba0 100644 --- a/Bio/PDB/PDBList.py +++ b/Bio/PDB/PDBList.py @@ -22,6 +22,7 @@ """Access the PDB over the internet (for example to download structures).""" +import contextlib import gzip import os import shutil @@ -87,13 +88,12 @@ def get_status_list(self,url): Typical contents of the list files parsed by this method is now very simply one PDB name per line. """ - handle = _urlopen(url) - answer = [] - for line in handle: - pdb = line.strip() - assert len(pdb)==4 - answer.append(pdb) - handle.close() + with contextlib.closing(_urlopen(url)) as handle: + answer = [] + for line in handle: + pdb = line.strip() + assert len(pdb)==4 + answer.append(pdb) return answer def get_recent_changes(self): @@ -110,11 +110,13 @@ def get_recent_changes(self): drwxrwxr-x 2 1002 sysadmin 512 Oct 14 02:14 20031013 -rw-r--r-- 1 1002 sysadmin 1327 Mar 12 2001 README """ - url = _urlopen(self.pdb_server + '/pub/pdb/data/status/') - recent = filter(str.isdigit, - (x.split()[-1] for x in url.readlines()) - )[-1] - path = self.pdb_server+'/pub/pdb/data/status/%s/'%(recent) + url = self.pdb_server + '/pub/pdb/data/status/' + with contextlib.closing(_urlopen(url)) as handle: + recent = filter(str.isdigit, + (x.split()[-1] for x in handle.readlines()) + )[-1] + + path = self.pdb_server + '/pub/pdb/data/status/%s/' % (recent) # Retrieve the lists added = self.get_status_list(path+'added.pdb') modified = self.get_status_list(path+'modified.pdb') @@ -127,9 +129,11 @@ def get_all_entries(self): Returns a list of PDB codes in the index file. """ print "retrieving index file. Takes about 5 MB." - url = _urlopen(self.pdb_server + - '/pub/pdb/derived_data/index/entries.idx') - return [line[:4] for line in url.readlines()[2:] if len(line) > 4] + url = self.pdb_server + '/pub/pdb/derived_data/index/entries.idx' + with contextlib.closing(_urlopen(url)) as handle: + all_entries = [line[:4] for line in handle.readlines()[2:] + if len(line) > 4] + return all_entries def get_all_obsolete(self): """Returns a list of all obsolete entries ever in the PDB. @@ -154,18 +158,17 @@ def get_all_obsolete(self): ... """ - handle = _urlopen(self.pdb_server + - '/pub/pdb/data/status/obsolete.dat') - # Extract pdb codes. Could use a list comprehension, but I want - # to include an assert to check for mis-reading the data. - obsolete = [] - for line in handle: - if not line.startswith("OBSLTE "): - continue - pdb = line.split()[2] - assert len(pdb)==4 - obsolete.append(pdb) - handle.close() + url = self.pdb_server + '/pub/pdb/data/status/obsolete.dat' + with contextlib.closing(_urlopen(url)) as handle: + # Extract pdb codes. Could use a list comprehension, but I want + # to include an assert to check for mis-reading the data. + obsolete = [] + for line in handle: + if not line.startswith("OBSLTE "): + continue + pdb = line.split()[2] + assert len(pdb)==4 + obsolete.append(pdb) return obsolete def retrieve_pdb_file(self,pdb_code, obsolete=0, compression=None, @@ -241,11 +244,8 @@ def retrieve_pdb_file(self,pdb_code, obsolete=0, compression=None, urllib.urlretrieve(url, filename) # Uncompress the file - gz = gzip.open(filename, 'rb') - out = open(final_file, 'wb') - out.writelines(gz) - gz.close() - out.close() + with gzip.open(filename, 'rb') as gz, open(final_file, 'wb') as out: + out.writelines(gz) os.remove(filename) return final_file @@ -304,9 +304,8 @@ def download_entire_pdb(self, listfile=None): self.retrieve_pdb_file(pdb_code) # Write the list if listfile: - outfile = open(listfile, 'w') - outfile.writelines((x+'\n' for x in entries)) - outfile.close() + with open(listfile, 'w') as outfile: + outfile.writelines((x+'\n' for x in entries)) def download_obsolete_entries(self, listfile=None): """Retrieve all obsolete PDB entries not present in the local obsolete @@ -321,22 +320,18 @@ def download_obsolete_entries(self, listfile=None): # Write the list if listfile: - outfile = open(listfile, 'w') - outfile.writelines((x+'\n' for x in entries)) - outfile.close() + with open(listfile, 'w') as outfile: + outfile.writelines((x+'\n' for x in entries)) def get_seqres_file(self,savefile='pdb_seqres.txt'): """Retrieves a (big) file containing all the sequences of PDB entries and writes it to a file. """ print "retrieving sequence file. Takes about 15 MB." - handle = _urlopen(self.pdb_server + - '/pub/pdb/derived_data/pdb_seqres.txt') - lines = handle.readlines() - outfile = open(savefile, 'w') - outfile.writelines(lines) - outfile.close() - handle.close() + url = self.pdb_server + '/pub/pdb/derived_data/pdb_seqres.txt' + with contextlib.closing(_urlopen(url)) as handle: + with open(savefile, 'w') as outfile: + outfile.writelines(handle.readlines()) if __name__ == '__main__': From 8f529490ab61ad5c0ef3b89c906b659849d09e67 Mon Sep 17 00:00:00 2001 From: David Cain Date: Wed, 9 Jan 2013 16:33:58 -0500 Subject: [PATCH 03/10] Collapse unwieldy if-else structure --- Bio/PDB/PDBList.py | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/Bio/PDB/PDBList.py b/Bio/PDB/PDBList.py index b8f6d763ba0..39c521859dc 100644 --- a/Bio/PDB/PDBList.py +++ b/Bio/PDB/PDBList.py @@ -200,28 +200,16 @@ def retrieve_pdb_file(self,pdb_code, obsolete=0, compression=None, # Get the structure code=pdb_code.lower() filename="pdb%s.ent.gz"%code - if not obsolete: - url=(self.pdb_server+ - '/pub/pdb/data/structures/divided/pdb/%s/pdb%s.ent.gz' - % (code[1:3],code)) - else: - url=(self.pdb_server+ - '/pub/pdb/data/structures/obsolete/pdb/%s/pdb%s.ent.gz' - % (code[1:3],code)) + pdb_dir = "divided" if not obsolete else "obsolete" + url = (self.pdb_server + + '/pub/pdb/data/structures/%s/pdb/%s/%s' % + (pdb_dir, code[1:3], archive_fn)) # In which dir to put the pdb file? if pdir is None: - if self.flat_tree: - if not obsolete: - path=self.local_pdb - else: - path=self.obsolete_pdb - else: - # Put in PDB-style directory tree - if not obsolete: - path=os.path.join(self.local_pdb, code[1:3]) - else: - path=os.path.join(self.obsolete_pdb,code[1:3]) + path = self.local_pdb if not obsolete else self.obsolete_pdb + if not self.flat_tree: # Put in PDB-style directory tree + path = os.path.join(path, code[1:3]) else: # Put in specified directory path=pdir From 7f6b7121521f3149dcc0ba5cb7d2ec58a4293dca Mon Sep 17 00:00:00 2001 From: David Cain Date: Wed, 9 Jan 2013 16:38:34 -0500 Subject: [PATCH 04/10] PEP8 fixes within retrieve_pdb_file No functional changes, just readability fixes. --- Bio/PDB/PDBList.py | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/Bio/PDB/PDBList.py b/Bio/PDB/PDBList.py index 39c521859dc..202577b584f 100644 --- a/Bio/PDB/PDBList.py +++ b/Bio/PDB/PDBList.py @@ -171,8 +171,8 @@ def get_all_obsolete(self): obsolete.append(pdb) return obsolete - def retrieve_pdb_file(self,pdb_code, obsolete=0, compression=None, - uncompress=None, pdir=None): + def retrieve_pdb_file(self, pdb_code, obsolete=0, compression=None, + uncompress=None, pdir=None): """ Retrieves a PDB structure file from the PDB server and stores it in a local file tree. The PDB structure is returned as a single string. @@ -190,16 +190,16 @@ def retrieve_pdb_file(self,pdb_code, obsolete=0, compression=None, # Alert the user about deprecated parameters if compression is not None: warnings.warn("PDB file servers now only host .gz archives: " - "the compression parameter will not do anything" - , BiopythonDeprecationWarning) + "the compression parameter will not do anything", + BiopythonDeprecationWarning) if uncompress is not None: warnings.warn("Decompression is handled with the gzip module: " - "the uncompression parameter will not do anything" - , BiopythonDeprecationWarning) + "the uncompression parameter will not do anything", + BiopythonDeprecationWarning) # Get the structure - code=pdb_code.lower() - filename="pdb%s.ent.gz"%code + code = pdb_code.lower() + archive_fn = "pdb%s.ent.gz" % code pdb_dir = "divided" if not obsolete else "obsolete" url = (self.pdb_server + '/pub/pdb/data/structures/%s/pdb/%s/%s' % @@ -210,16 +210,15 @@ def retrieve_pdb_file(self,pdb_code, obsolete=0, compression=None, path = self.local_pdb if not obsolete else self.obsolete_pdb if not self.flat_tree: # Put in PDB-style directory tree path = os.path.join(path, code[1:3]) - else: - # Put in specified directory - path=pdir + else: # Put in specified directory + path = pdir - if not os.access(path,os.F_OK): + if not os.access(path, os.F_OK): os.makedirs(path) - filename=os.path.join(path, filename) + filename = os.path.join(path, archive_fn) # the final uncompressed file - final_file=os.path.join(path, "pdb%s.ent" % code) + final_file = os.path.join(path, "pdb%s.ent" % code) # Skip download if the file already exists if not self.overwrite: From d6f38a1cec224578f2ebfb72d583f20cfa355a8a Mon Sep 17 00:00:00 2001 From: David Cain Date: Wed, 9 Jan 2013 16:46:36 -0500 Subject: [PATCH 05/10] Remove deprecated parameters Obsolete parameters (which were rarely specified by users anyway) gave warnings in version 1.57. They should be able to be safely removed now. --- Bio/PDB/PDBList.py | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/Bio/PDB/PDBList.py b/Bio/PDB/PDBList.py index 202577b584f..15f8edfe09a 100644 --- a/Bio/PDB/PDBList.py +++ b/Bio/PDB/PDBList.py @@ -28,9 +28,6 @@ import shutil import urllib from urllib2 import urlopen as _urlopen # urllib made too many FTP conn's -import warnings - -from Bio import BiopythonDeprecationWarning class PDBList(object): @@ -171,15 +168,12 @@ def get_all_obsolete(self): obsolete.append(pdb) return obsolete - def retrieve_pdb_file(self, pdb_code, obsolete=0, compression=None, - uncompress=None, pdir=None): + def retrieve_pdb_file(self, pdb_code, obsolete=False, pdir=None): """ Retrieves a PDB structure file from the PDB server and stores it in a local file tree. - The PDB structure is returned as a single string. - If obsolete==1, the file will be saved in a special file tree. - If uncompress is specified, a system utility will decompress the .gz - archive. Otherwise, Python gzip utility will handle it. - compression does nothing, as all archives are already in .gz format + + The PDB structure's file name is returned as a single string. + If obsolete == True, the file will be saved in a special file tree. @param pdir: put the file in this directory (default: create a PDB-style directory tree) @type pdir: string @@ -187,16 +181,6 @@ def retrieve_pdb_file(self, pdb_code, obsolete=0, compression=None, @return: filename @rtype: string """ - # Alert the user about deprecated parameters - if compression is not None: - warnings.warn("PDB file servers now only host .gz archives: " - "the compression parameter will not do anything", - BiopythonDeprecationWarning) - if uncompress is not None: - warnings.warn("Decompression is handled with the gzip module: " - "the uncompression parameter will not do anything", - BiopythonDeprecationWarning) - # Get the structure code = pdb_code.lower() archive_fn = "pdb%s.ent.gz" % code From 23babf617fdee2eacce67dbfdff5cbdd96478088 Mon Sep 17 00:00:00 2001 From: David Cain Date: Wed, 9 Jan 2013 16:49:22 -0500 Subject: [PATCH 06/10] Update with clarifying comments --- Bio/PDB/PDBList.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Bio/PDB/PDBList.py b/Bio/PDB/PDBList.py index 15f8edfe09a..0bda263d8bb 100644 --- a/Bio/PDB/PDBList.py +++ b/Bio/PDB/PDBList.py @@ -181,7 +181,7 @@ def retrieve_pdb_file(self, pdb_code, obsolete=False, pdir=None): @return: filename @rtype: string """ - # Get the structure + # Get the compressed PDB structure code = pdb_code.lower() archive_fn = "pdb%s.ent.gz" % code pdb_dir = "divided" if not obsolete else "obsolete" @@ -189,20 +189,18 @@ def retrieve_pdb_file(self, pdb_code, obsolete=False, pdir=None): '/pub/pdb/data/structures/%s/pdb/%s/%s' % (pdb_dir, code[1:3], archive_fn)) - # In which dir to put the pdb file? + # Where does the final PDB file get saved? if pdir is None: path = self.local_pdb if not obsolete else self.obsolete_pdb if not self.flat_tree: # Put in PDB-style directory tree path = os.path.join(path, code[1:3]) else: # Put in specified directory path = pdir - if not os.access(path, os.F_OK): os.makedirs(path) filename = os.path.join(path, archive_fn) - # the final uncompressed file - final_file = os.path.join(path, "pdb%s.ent" % code) + final_file = os.path.join(path, "pdb%s.ent" % code) # (decompressed) # Skip download if the file already exists if not self.overwrite: @@ -214,7 +212,7 @@ def retrieve_pdb_file(self, pdb_code, obsolete=False, pdir=None): print "Downloading PDB structure '%s'..." % pdb_code urllib.urlretrieve(url, filename) - # Uncompress the file + # Uncompress the archive, delete when done with gzip.open(filename, 'rb') as gz, open(final_file, 'wb') as out: out.writelines(gz) os.remove(filename) From 7f04a109914262cd92f5bc475b71010287aead8a Mon Sep 17 00:00:00 2001 From: David Cain Date: Wed, 9 Jan 2013 16:57:21 -0500 Subject: [PATCH 07/10] PEP8 fixes, updated comments for file Does not functionally change code, only adds appropriate spacing, updates comments where applicable. --- Bio/PDB/PDBList.py | 57 ++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/Bio/PDB/PDBList.py b/Bio/PDB/PDBList.py index 0bda263d8bb..b9e89a49a19 100644 --- a/Bio/PDB/PDBList.py +++ b/Bio/PDB/PDBList.py @@ -4,8 +4,6 @@ # # A tool for tracking changes in the PDB Protein Structure Database. # -# Version 2.0 -# # (c) 2003 Kristian Rother # This work was supported by the German Ministry of Education # and Research (BMBF). Project http://www.bcbio.de @@ -15,12 +13,12 @@ # email : krother@genesilico.pl # # -# This Code is released under the conditions of the Biopython license. +# This code is released under the conditions of the Biopython license. # It may be distributed freely with respect to the original author. -# Any maintainer of the BioPython code may change this notice +# Any maintainer of the Biopython code may change this notice # when appropriate. -"""Access the PDB over the internet (for example to download structures).""" +""" Access the PDB over the internet (e.g. to download structures). """ import contextlib import gzip @@ -42,13 +40,13 @@ class PDBList(object): To use it properly, prepare a directory /pdb or the like, where PDB files are stored. - If You want to use this module from inside a proxy, add - the proxy variable to Your environment, e.g. in Unix + If you want to use this module from inside a proxy, add + the proxy variable to your environment, e.g. in Unix: export HTTP_PROXY='http://realproxy.charite.de:888' (This can also be added to ~/.bashrc) """ - PDB_REF=""" + PDB_REF = """ The Protein Data Bank: a computer-based archival file for macromolecular structures. F.C.Bernstein, T.F.Koetzle, G.J.B.Williams, E.F.Meyer Jr, M.D.Brice, J.R.Rodgers, O.Kennard, T.Shimanouchi, M.Tasumi J. Mol. Biol. 112 pp. 535-542 (1977) @@ -58,27 +56,25 @@ class PDBList(object): alternative_download_url = "http://www.rcsb.org/pdb/files/" # just append PDB code to this, and then it works. - def __init__(self,server='ftp://ftp.wwpdb.org', pdb=os.getcwd(), obsolete_pdb=None): + def __init__(self, server='ftp://ftp.wwpdb.org', pdb=os.getcwd(), + obsolete_pdb=None): """Initialize the class with the default server or a custom one.""" - # remote pdb server - self.pdb_server = server - - # local pdb file tree - self.local_pdb = pdb + self.pdb_server = server # remote pdb server + self.local_pdb = pdb # local pdb file tree # local file tree for obsolete pdb files if obsolete_pdb: self.obsolete_pdb = obsolete_pdb else: self.obsolete_pdb = os.path.join(self.local_pdb, 'obsolete') - if not os.access(self.obsolete_pdb,os.F_OK): + if not os.access(self.obsolete_pdb, os.F_OK): os.makedirs(self.obsolete_pdb) # variables for command-line options self.overwrite = 0 self.flat_tree = 0 - def get_status_list(self,url): + def get_status_list(self, url): """Retrieves a list of pdb codes in the weekly pdb status file from the given URL. Used by get_recent_files. @@ -89,7 +85,7 @@ def get_status_list(self,url): answer = [] for line in handle: pdb = line.strip() - assert len(pdb)==4 + assert len(pdb) == 4 answer.append(pdb) return answer @@ -114,11 +110,12 @@ def get_recent_changes(self): )[-1] path = self.pdb_server + '/pub/pdb/data/status/%s/' % (recent) + # Retrieve the lists - added = self.get_status_list(path+'added.pdb') - modified = self.get_status_list(path+'modified.pdb') - obsolete = self.get_status_list(path+'obsolete.pdb') - return [added,modified,obsolete] + added = self.get_status_list(path + 'added.pdb') + modified = self.get_status_list(path + 'modified.pdb') + obsolete = self.get_status_list(path + 'obsolete.pdb') + return [added, modified, obsolete] def get_all_entries(self): """Retrieves a big file containing all the @@ -164,7 +161,7 @@ def get_all_obsolete(self): if not line.startswith("OBSLTE "): continue pdb = line.split()[2] - assert len(pdb)==4 + assert len(pdb) == 4 obsolete.append(pdb) return obsolete @@ -231,7 +228,7 @@ def update_pdb(self): new, modified, obsolete = self.get_recent_changes() - for pdb_code in new+modified: + for pdb_code in new + modified: try: self.retrieve_pdb_file(pdb_code) except Exception: @@ -274,7 +271,7 @@ def download_entire_pdb(self, listfile=None): # Write the list if listfile: with open(listfile, 'w') as outfile: - outfile.writelines((x+'\n' for x in entries)) + outfile.writelines((x + '\n' for x in entries)) def download_obsolete_entries(self, listfile=None): """Retrieve all obsolete PDB entries not present in the local obsolete @@ -290,9 +287,9 @@ def download_obsolete_entries(self, listfile=None): # Write the list if listfile: with open(listfile, 'w') as outfile: - outfile.writelines((x+'\n' for x in entries)) + outfile.writelines((x + '\n' for x in entries)) - def get_seqres_file(self,savefile='pdb_seqres.txt'): + def get_seqres_file(self, savefile='pdb_seqres.txt'): """Retrieves a (big) file containing all the sequences of PDB entries and writes it to a file. """ @@ -325,10 +322,10 @@ def get_seqres_file(self,savefile='pdb_seqres.txt'): """ print doc - if len(sys.argv)>2: + if len(sys.argv) > 2: pdb_path = sys.argv[2] pl = PDBList(pdb=pdb_path) - if len(sys.argv)>3: + if len(sys.argv) > 3: for option in sys.argv[3:]: if option == '-d': pl.flat_tree = 1 @@ -343,7 +340,7 @@ def get_seqres_file(self,savefile='pdb_seqres.txt'): if len(sys.argv) > 1: if sys.argv[1] == 'update': # update PDB - print "updating local PDB at "+pdb_path + print "updating local PDB at " + pdb_path pl.update_pdb() elif sys.argv[1] == 'all': @@ -356,4 +353,4 @@ def get_seqres_file(self,savefile='pdb_seqres.txt'): elif len(sys.argv[1]) == 4 and sys.argv[1][0].isdigit(): # get single PDB entry - pl.retrieve_pdb_file(sys.argv[1],pdir=pdb_path) + pl.retrieve_pdb_file(sys.argv[1], pdir=pdb_path) From fa9801c83837d85aa59e811ab7f2bbe5a1519533 Mon Sep 17 00:00:00 2001 From: David Cain Date: Wed, 9 Jan 2013 17:49:44 -0500 Subject: [PATCH 08/10] Use urlretrieve in other instance of save to disk --- Bio/PDB/PDBList.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Bio/PDB/PDBList.py b/Bio/PDB/PDBList.py index b9e89a49a19..ec7e896afbd 100644 --- a/Bio/PDB/PDBList.py +++ b/Bio/PDB/PDBList.py @@ -293,11 +293,9 @@ def get_seqres_file(self, savefile='pdb_seqres.txt'): """Retrieves a (big) file containing all the sequences of PDB entries and writes it to a file. """ - print "retrieving sequence file. Takes about 15 MB." + print "Retrieving sequence file (takes about 15 MB)." url = self.pdb_server + '/pub/pdb/derived_data/pdb_seqres.txt' - with contextlib.closing(_urlopen(url)) as handle: - with open(savefile, 'w') as outfile: - outfile.writelines(handle.readlines()) + urllib.urlretrieve(url, savefile) if __name__ == '__main__': From 5ba3ba13de4097bd538c609833f0fa97a79e1438 Mon Sep 17 00:00:00 2001 From: David Cain Date: Thu, 10 Jan 2013 00:20:42 -0500 Subject: [PATCH 09/10] Import with_statement for backwards compatibility --- Bio/PDB/PDBList.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Bio/PDB/PDBList.py b/Bio/PDB/PDBList.py index ec7e896afbd..da008f9cde5 100644 --- a/Bio/PDB/PDBList.py +++ b/Bio/PDB/PDBList.py @@ -20,6 +20,9 @@ """ Access the PDB over the internet (e.g. to download structures). """ +# For using with statement in Python 2.5 or Jython +from __future__ import with_statement + import contextlib import gzip import os From a6d4cf32b72029df71e186a9cf4a210fa7026b85 Mon Sep 17 00:00:00 2001 From: David Cain Date: Wed, 9 Jan 2013 20:10:40 -0500 Subject: [PATCH 10/10] Nest one-lined with statements Evidently, the comma syntax for two with statements is a Python 2.7 feature. --- Bio/PDB/PDBList.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Bio/PDB/PDBList.py b/Bio/PDB/PDBList.py index da008f9cde5..55fedef9a02 100644 --- a/Bio/PDB/PDBList.py +++ b/Bio/PDB/PDBList.py @@ -213,8 +213,9 @@ def retrieve_pdb_file(self, pdb_code, obsolete=False, pdir=None): urllib.urlretrieve(url, filename) # Uncompress the archive, delete when done - with gzip.open(filename, 'rb') as gz, open(final_file, 'wb') as out: - out.writelines(gz) + with gzip.open(filename, 'rb') as gz: + with open(final_file, 'wb') as out: + out.writelines(gz) os.remove(filename) return final_file