1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
|
From 62fcfcfba8b3fb597ce00b1844bc7ebb3b54e70f Mon Sep 17 00:00:00 2001
From: Matthew Burn <matthew.burn@imperagen.com>
Date: Mon, 3 Feb 2025 09:58:09 +0000
Subject: [PATCH 1/3] Removed `numpy.compat` and added `asbytes` and `asstr`
---
parmed/utils/netcdf.py | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
--- a/parmed/utils/netcdf.py
+++ b/parmed/utils/netcdf.py
@@ -39,15 +39,25 @@
from operator import mul
from collections import OrderedDict
from platform import python_implementation
+from typing import Any
import mmap as mm
import numpy as np
-from numpy.compat import asbytes, asstr
from numpy import frombuffer, dtype, empty, array, asarray
from numpy import little_endian as LITTLE_ENDIAN
from functools import reduce
+def asbytes(s: Any) -> bytes:
+ """Ensures input is in bytes format. Mimics numpy.compat.asbytes"""
+ return str(s).encode("latin1") if isinstance(s, str) else s
+
+
+def asstr(b: Any) -> str:
+ """Ensures input is in string format. Mimics numpy.compat.asstr"""
+ return b.decode("latin1") if isinstance(b, bytes) else str(b)
+
+
IS_PYPY = python_implementation() == 'PyPy'
--- a/parmed/formats/pdb.py
+++ b/parmed/formats/pdb.py
@@ -7,9 +7,11 @@
from functools import lru_cache, reduce
from string import ascii_letters
import io
-import ftplib
+import urllib
import gzip
import logging
+import urllib.error
+import urllib.request
import numpy as np
from ..exceptions import PDBError, PDBWarning
from ..formats.pdbx import PdbxReader, PdbxWriter, containers
@@ -311,16 +313,18 @@
raise ValueError('pdb_id must be the 4-letter PDB code')
pdb_id = pdb_id.lower()
- ftp = ftplib.FTP('ftp.wwpdb.org', timeout=timeout)
- ftp.login()
+
+ url = (
+ 'https://files.wwpdb.org/pub/pdb/data/structures/divided/pdb/%s/pdb%s.ent.gz'
+ ) % (pdb_id[1:3], pdb_id)
+
fileobj = io.BytesIO()
try:
- ftp_loc = f"/pub/pdb/data/structures/divided/pdb/{pdb_id[1:3]}/pdb{pdb_id}.ent.gz"
- ftp.retrbinary(f"RETR {ftp_loc}", fileobj.write)
- except ftplib.all_errors as err:
+ with urllib.request.urlopen(url, timeout=timeout) as response:
+ fileobj.write(response.read())
+ except (urllib.error.URLError, urllib.error.HTTPError) as err:
raise IOError(f"Could not retrieve PDB ID {pdb_id}; {err}") from err
- finally:
- ftp.close()
+
# Rewind, wrap it in a GzipFile and send it to parse
fileobj.seek(0)
fileobj = io.TextIOWrapper(gzip.GzipFile(fileobj=fileobj, mode='r'))
@@ -1180,17 +1184,18 @@
raise ValueError('pdb_id must be the 4-letter PDB code')
pdb_id = pdb_id.lower()
- ftp = ftplib.FTP('ftp.wwpdb.org', timeout=timeout)
- ftp.login()
+
+ url = (
+ 'https://files.wwpdb.org/pub/pdb/data/structures/divided/mmCIF/%s/%s.cif.gz'
+ ) % (pdb_id[1:3], pdb_id)
+
fileobj = io.BytesIO()
try:
- ftp.retrbinary('RETR /pub/pdb/data/structures/divided/mmCIF/'
- '%s/%s.cif.gz' % (pdb_id[1:3], pdb_id),
- fileobj.write)
- except ftplib.all_errors as err:
- raise IOError('Could not retrieve PDB ID %s; %s' % (pdb_id, err))
- finally:
- ftp.close()
+ with urllib.request.urlopen(url, timeout=timeout) as response:
+ fileobj.write(response.read())
+ except (urllib.error.URLError, urllib.error.HTTPError) as err:
+ raise IOError(f"Could not retrieve PDB ID {pdb_id}; {err}") from err
+
fileobj.seek(0)
fileobj = io.TextIOWrapper(gzip.GzipFile(fileobj=fileobj, mode='r'))
if saveto is not None:
--- a/test/test_parmed_genopen.py
+++ b/test/test_parmed_genopen.py
@@ -75,7 +75,8 @@
self.assertEqual(f.read(), genopen(get_fn('4lzt.pdb.gz')).read())
@unittest.skip("Not running tests requiring network access")
- @unittest.skipUnless(is_local(), 'Cannot download files from PDB with CI systems')
+ # @unittest.skipUnless(is_local(), 'Cannot download files from PDB with CI systems')
+ @unittest.skip('RCSB deprecated FTP protocol https://www.rcsb.org/news/feature/65562f0ad78e004e766a96c1')
def test_read_ftp_URL(self):
""" Tests genopen reading a ftp remote file """
url = 'ftp://ftp.wwpdb.org/pub/pdb/data/structures/divided/mmCIF/05/205l.cif.gz'
|