Skip to content

Commit

Permalink
Upgrades for Python 3.12
Browse files Browse the repository at this point in the history
- Replace `imp.load_source`
- Fix invalid escape sequences (W605)
- Require Python 3.6+
  • Loading branch information
speleo3 committed Dec 21, 2023
1 parent 07d598d commit b4e94d5
Show file tree
Hide file tree
Showing 14 changed files with 62 additions and 49 deletions.
5 changes: 2 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ package consists of a few major components:

Installation
------------
CSB is being developed on Linux with Python 2.7 and 3.6. However, compatibility
CSB is being developed on Linux. However, compatibility
is a design goal and the package works on any platform, on any modern Python
interpreter since version 2.6 (that includes python 3 support out of
the box). If you find any issues on a platform/interpreter different from
interpreter. If you find any issues on a platform/interpreter different from
our development environment, please let us know.

CSB and all of its dependencies can be installed with pip::
Expand Down
6 changes: 3 additions & 3 deletions csb/bio/io/hhpred.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ def _parse_properties(self, hmm):
hmm.family = line[6:].strip()

elif line.startswith('LENG '):
m = re.search('(\d+)\D+(\d+)', line).groups()
m = re.search(r'(\d+)\D+(\d+)', line).groups()
m = tuple(map(int, m))
hmm.length = ProfileLength(m[0], m[1])

Expand Down Expand Up @@ -257,7 +257,7 @@ def _parse_sequences(self, hmm):
if header_token in ['>ss_dssp', '>sa_dssp', '>ss_pred', '>ss_conf', '>Consens']:

lines = entry.strip().splitlines()
seq = re.sub('\s+', '', ''.join(lines[1:]))
seq = re.sub(r'\s+', '', ''.join(lines[1:]))

if header_token == '>ss_dssp':
hmm.dssp = structure.SecondaryStructure(seq)
Expand Down Expand Up @@ -304,7 +304,7 @@ def _parse_profile(self, hmm, units=ScoreUnits.LogScales):
start_probs = None

lines = iter(self._profile)
pattern = re.compile('^[A-Z\-]\s[0-9]+\s+')
pattern = re.compile(r'^[A-Z\-]\s[0-9]+\s+')

if units == ScoreUnits.LogScales:

Expand Down
20 changes: 10 additions & 10 deletions csb/bio/io/procheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@ def parse(self, fn):
f_handler = open(os.path.expanduser(fn))
text = f_handler.read()

input_file_name = re.compile('>>>-----.*?\n.*?\n\s*\|\s*(\S+)\s+')
residues = re.compile('(\d+)\s*residues\s\|')
ramachandran_plot = re.compile('Ramachandran\splot:\s*(\d+\.\d+)' +
'%\s*core\s*(\d+\.\d+)%\s*allow\s*(\d+\.\d+)' +
'%\s*gener\s*(\d+\.\d+)%\s*disall')
labelled_all = re.compile('Ramachandrans:\s*(\d+)\s*.*?out\sof\s*(\d+)')
labelled_chi = re.compile('Chi1-chi2\splots:\s*(\d+)\s*.*?out\sof\s*(\d+)')
bad_contacts = re.compile('Bad\scontacts:\s*(\d+)')
g_factors = re.compile('G-factors\s*Dihedrals:\s*([0-9-+.]+)' +
'\s*Covalent:\s*([0-9-+.]+)\s*Overall:\s*([0-9-+.]+)')
input_file_name = re.compile('>>>-----.*?\n.*?\n' r'\s*\|\s*(\S+)\s+')
residues = re.compile(r'(\d+)\s*residues\s\|')
ramachandran_plot = re.compile(r'Ramachandran\splot:\s*(\d+\.\d+)' +
r'%\s*core\s*(\d+\.\d+)%\s*allow\s*(\d+\.\d+)' +
r'%\s*gener\s*(\d+\.\d+)%\s*disall')
labelled_all = re.compile(r'Ramachandrans:\s*(\d+)\s*.*?out\sof\s*(\d+)')
labelled_chi = re.compile(r'Chi1-chi2\splots:\s*(\d+)\s*.*?out\sof\s*(\d+)')
bad_contacts = re.compile(r'Bad\scontacts:\s*(\d+)')
g_factors = re.compile(r'G-factors\s*Dihedrals:\s*([0-9-+.]+)' +
r'\s*Covalent:\s*([0-9-+.]+)\s*Overall:\s*([0-9-+.]+)')

info['input_file'] = input_file_name.search(text).groups()[0]
info['#residues'] = int(residues.search(text).groups()[0])
Expand Down
10 changes: 5 additions & 5 deletions csb/bio/io/whatif.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ def parse_summary(self, fn):
text = f_handler.read()

info = dict()
re_ramachandran = re.compile('Ramachandran\s*Z-score\s*:\s*([0-9.Ee-]+)')
re_1st = re.compile('1st\s*generation\s*packing\s*quality\s*:\s*([0-9.Ee-]+)')
re_2nd = re.compile('2nd\s*generation\s*packing\s*quality\s*:\s*([0-9.Ee-]+)')
re_backbone = re.compile('Backbone\s*conformation\s*Z-score\s*:\s*([0-9.Ee-]+)')
re_rotamer = re.compile('chi-1\S*chi-2\s*rotamer\s*normality\s*:\s*([0-9.Ee-]+)')
re_ramachandran = re.compile(r'Ramachandran\s*Z-score\s*:\s*([0-9.Ee-]+)')
re_1st = re.compile(r'1st\s*generation\s*packing\s*quality\s*:\s*([0-9.Ee-]+)')
re_2nd = re.compile(r'2nd\s*generation\s*packing\s*quality\s*:\s*([0-9.Ee-]+)')
re_backbone = re.compile(r'Backbone\s*conformation\s*Z-score\s*:\s*([0-9.Ee-]+)')
re_rotamer = re.compile(r'chi-1\S*chi-2\s*rotamer\s*normality\s*:\s*([0-9.Ee-]+)')


info['rama_z_score'] = float(re_ramachandran.search(text).groups(0)[0])
Expand Down
2 changes: 1 addition & 1 deletion csb/bio/io/wwpdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -1219,7 +1219,7 @@ def _read_resolution(self, line):
@return: resolution
@rtype: float or None
"""
res = re.search("(\d+(?:\.\d+)?)\s+ANGSTROM", line)
res = re.search(r"(\d+(?:\.\d+)?)\s+ANGSTROM", line)

if res and res.groups():
return float(res.group(1))
Expand Down
2 changes: 1 addition & 1 deletion csb/bio/sequence/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ def __init__(self, id, header, residues, type=SequenceTypes.Unknown):

def _append(self, string):
# this seems to be the fastest method for sanitization and storage
self._residues += re.sub('([^\w\-\.])+', '', string)
self._residues += re.sub(r'([^\w\-\.])+', '', string)

def _add(self, char):
self._append(char)
Expand Down
4 changes: 2 additions & 2 deletions csb/bio/structure/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2126,9 +2126,9 @@ def parse(string, conf_string=None):
if not isinstance(string, csb.core.string):
raise TypeError(string)

string = ''.join(re.split('\s+', string))
string = ''.join(re.split(r'\s+', string))
if conf_string is not None:
conf_string = ''.join(re.split('\s+', conf_string))
conf_string = ''.join(re.split(r'\s+', conf_string))
if not len(string) == len(conf_string):
raise ValueError('The confidence string has unexpected length.')
motifs = [ ]
Expand Down
20 changes: 13 additions & 7 deletions csb/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
source trees.
@see: [CSB 0000038]
"""
from __future__ import print_function

import os
import sys
Expand Down Expand Up @@ -55,7 +54,7 @@
"""
It is now safe to import any modules
"""
import imp
import importlib
import shutil
import tarfile

Expand All @@ -65,6 +64,13 @@
from csb.io import Shell


def _load_source(name, pathname):
spec = importlib.util.spec_from_file_location(name, pathname)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module


class BuildTypes(object):
"""
Enumeration of build types.
Expand Down Expand Up @@ -288,7 +294,7 @@ def _doc(self, version):
epydoc.cli.cli()
sys.exit(0)
except SystemExit as ex:
if ex.code is 0:
if ex.code == 0:
self.log('\n Passed all doc tests')
else:
if ex.code == 2:
Expand Down Expand Up @@ -333,7 +339,7 @@ def _package(self):
version = package = None

try:
setup = imp.load_source('setupcsb', 'setup.py')
setup = _load_source('setupcsb', 'setup.py')
d = setup.build()
version = setup.VERSION
package = d.dist_files[0][2]
Expand All @@ -342,7 +348,7 @@ def _package(self):
self._strip_source(package)

except SystemExit as ex:
if ex.code is not 0:
if ex.code != 0:
self.log('\n FAIL: Setup returned: \n\n{0}\n'.format(ex))
self._success = False
package = 'FAIL'
Expand Down Expand Up @@ -474,7 +480,7 @@ def __init__(self, path, sc):
self._path = path
else:
raise IOError('Path not found: {0}'.format(path))
if Shell.run([sc, 'help']).code is 0:
if Shell.run([sc, 'help']).code == 0:
self._sc = sc
else:
raise RevisionError('Source control binary probe failed', None, None)
Expand Down Expand Up @@ -518,7 +524,7 @@ def write(self, revision, sourcefile):
src.write(line)

self._delcache(sourcefile)
return imp.load_source('____source', sourcefile).__version__
return _load_source('____source', sourcefile).__version__

def _run(self, cmd):

Expand Down
2 changes: 1 addition & 1 deletion csb/statistics/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ def running_average(x, w, axis=None):
return array([mean(x[i:i + w], axis) for i in range(len(x) - w)])

def weighted_median(x, w):
"""
r"""
Calculates the weighted median, that is the minimizer of
argmin {\sum w_i |x_i - \mu|}
Expand Down
10 changes: 7 additions & 3 deletions csb/test/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def testSomeFeature(self)
"""
import os
import sys
import imp
import importlib
import types
import time
import tempfile
Expand Down Expand Up @@ -443,7 +443,7 @@ def execute(cls):

return runner.run(suite)

class InvalidNamespaceError(NameError, ImportError):
class InvalidNamespaceError(ImportError):
pass

class AbstractTestBuilder(object):
Expand Down Expand Up @@ -567,7 +567,11 @@ def _loadSource(self, path):
name = os.path.splitext(os.path.abspath(path))[0]
name = name.replace('.', '-').rstrip('__init__').strip(os.path.sep)

return imp.load_source(name, path)
spec = importlib.util.spec_from_file_location(name, path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)

return module

def _recurse(self, obj):
"""
Expand Down
5 changes: 3 additions & 2 deletions csb/test/cases/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def runTest(self):
copy = utils.deepcopy(obj, recursion=(rec + 1))

self.assertEqual(obj, copy)
self.assertNotEquals(id(obj), id(copy))
self.assertNotEqual(id(obj), id(copy))

@test.unit
class TestIterable(test.Case):
Expand Down Expand Up @@ -70,7 +70,8 @@ def test():
def testComparison(self):
self.assertEqual(self.enum.A, 0)
self.assertEqual(self.enum.C, 66)
self.assertFalse(self.enum.C is 66)
int_66 = 66
self.assertFalse(self.enum.C is int_66)
self.assertFalse(isinstance(self.enum.A, int))

def testStr(self):
Expand Down
2 changes: 1 addition & 1 deletion csb/test/cases/io/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ def setUp(self):
"Although that way may not be" + \
"obvious at first" + \
"unless you're Dutch.",
"([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])"]
r"([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])"]

# Completly connnected graph

Expand Down
8 changes: 7 additions & 1 deletion csb/test/cases/statistics/samplers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,12 @@ def clone(self):
return s


def _arrays_equal(a1, a2) -> bool:
if a1.shape != a2.shape:
return False
return (a1 == a2).all()


@test.functional
class TestReplicaHistory(test.Case):

Expand Down Expand Up @@ -863,7 +869,7 @@ def _assertIdenticalProjTrajs(self, samples, interval, first_swap=None):
ok = []
for i in range(len(samples[0])):
trajs2 = rh.calculate_projected_trajectories(i)
ok.append(True in [np.all(np.array(t1) == np.array(t2)) for t1 in trajs1
ok.append(True in [_arrays_equal(np.array(t1), np.array(t2)) for t1 in trajs1
for t2 in trajs2])

return np.all(ok)
Expand Down
15 changes: 6 additions & 9 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@
REQUIREMENTS = open("requirements.txt", encoding="utf-8").readlines()
DEV_REQUIREMENTS = []

if sys.version_info[0] == 2:
DEV_REQUIREMENTS.append("epydoc")

v = {}
exec(open(ROOT + "/__init__.py", encoding="utf-8").read(), v)
VERSION = v["Version"]()
Expand Down Expand Up @@ -69,13 +66,13 @@ def build():
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.1',
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Topic :: Scientific/Engineering',
'Topic :: Scientific/Engineering :: Bio-Informatics',
'Topic :: Scientific/Engineering :: Mathematics',
Expand Down

0 comments on commit b4e94d5

Please sign in to comment.