Skip to content

Commit

Permalink
Add python 3.12 to CI matrix (pysb#586)
Browse files Browse the repository at this point in the history
* Use raw strings for strings with incidental backslashes
* Correct spelling of now-renamed assert_raises_regex
* Work around Python 3.12 OrderedDict repr in doctest:
Python 3.12 changed the OrderedDict repr to emit a dict literal as the
constructor argument instead of a list of tuples. We have one doctest
that returns an OrderedDict, failing on 3.12 without this workaround.
This change adds a temporary monkeypatch to collections.OrderedDict
in the nose module-level fixture, but I don't like it.
  • Loading branch information
jmuhlich authored Feb 21, 2024
1 parent 23fc948 commit b053005
Show file tree
Hide file tree
Showing 8 changed files with 35 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
strategy:
matrix:
os: ["ubuntu-latest", "macos-latest", "windows-latest"]
python-version: ["3.8", "3.9", "3.10", "3.11"]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
defaults:
run:
shell: bash -l {0}
Expand Down
2 changes: 1 addition & 1 deletion pysb/bng.py
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,7 @@ def _parse_reaction(model, line, reaction_cache):
rule_list = rule_list.split(',') # BNG lists all rules that generate a rxn
# Support new (BNG 2.2.6-stable or greater) and old BNG naming convention
# for reverse rules
rule_name, is_reverse = zip(*[re.subn('^_reverse_|\(reverse\)$', '', r)
rule_name, is_reverse = zip(*[re.subn(r'^_reverse_|\(reverse\)$', '', r)
for r in rule_list])
is_reverse = tuple(bool(i) for i in is_reverse)
r_names = ['__s%d' % r for r in reactants]
Expand Down
6 changes: 3 additions & 3 deletions pysb/export/stochkit.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ def export(self, initials=None, param_values=None):

# Reactions
reacs = etree.Element('ReactionsList')
pattern = re.compile("(__s\d+)\*\*(\d+)")
pattern = re.compile(r"(__s\d+)\*\*(\d+)")
for rxn_id, rxn in enumerate(self.model.reactions):
rxn_name = 'Rxn%d' % rxn_id
rxn_desc = 'Rules: %s' % str(rxn["rule"])
Expand Down Expand Up @@ -325,6 +325,6 @@ def export(self, initials=None, param_values=None):
doc = etree.tostring(document)
xmldoc = xml.dom.minidom.parseString(doc)
uglyXml = xmldoc.toprettyxml(indent=' ')
text_re = re.compile(">\n\s+([^<>\s].*?)\n\s+</", re.DOTALL)
prettyXml = text_re.sub(">\g<1></", uglyXml)
text_re = re.compile(r">\n\s+([^<>\s].*?)\n\s+</", re.DOTALL)
prettyXml = text_re.sub(r">\g<1></", uglyXml)
return prettyXml
2 changes: 1 addition & 1 deletion pysb/importers/bngl.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ def _parse_initials(self):
try:
value = float(value_param)
# Need to create a new parameter for the initial conc. literal
name = re.sub('[^\w]+', '_', i.get('name').replace(
name = re.sub(r'[^\w]+', '_', i.get('name').replace(
')', '').replace('(', '')) + '_0'
try:
value_param = self.parameter(name, value)
Expand Down
2 changes: 1 addition & 1 deletion pysb/kappa.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""
r"""
Wrapper functions for running the Kappa programs *KaSim* and *KaSa*.
The path to the directory containing the KaSim and KaSa executables can be
Expand Down
24 changes: 24 additions & 0 deletions pysb/pattern.py
Original file line number Diff line number Diff line change
Expand Up @@ -1090,3 +1090,27 @@ def __cmp__(self, other):
def _repr_species_dict(self, species_dict):
return '{%s}' % ', '.join(["'__s%d': %s" % (k, self.species[k])
for k in sorted(species_dict.keys())])


# doctest fixtures


def setup_module(module):
# Patch OrderedDict repr to match Python 3.11 and earlier.
global _old_od
_old_od = collections.OrderedDict
class OrderedDict(_old_od):
def __repr__(self):
if not self:
return '%s()' % (self.__class__.__name__,)
return '%s(%r)' % (self.__class__.__name__, list(self.items()))
collections.OrderedDict = OrderedDict
setup_module.__test__ = False


def teardown_module(module):
# Restore OrderedDict.
global _old_od
collections.OrderedDict = _old_od
del _old_od
teardown_module.__test__ = False
4 changes: 2 additions & 2 deletions pysb/tests/test_bng.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from pysb.bng import *
import os
import unittest
from nose.tools import assert_raises_regexp
from nose.tools import assert_raises_regex
from pysb.generator.bng import BngPrinter
import sympy
import math
Expand Down Expand Up @@ -249,7 +249,7 @@ def test_bng_error():
Parameter('kf', 1)
# The following rule does not specify A's site on the RHS, so should generate a BNG error
Rule('r1', A(a='s1') >> A(), kf)
assert_raises_regexp(
assert_raises_regex(
BngInterfaceError,
'Molecule created in reaction rule: Component\(s\) a missing from molecule A\(\)',
generate_equations,
Expand Down
4 changes: 2 additions & 2 deletions pysb/tests/test_importers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from pysb.importers.bngl import model_from_bngl, BnglImportError
from pysb.importers.sbml import model_from_sbml, model_from_biomodels
import numpy
from nose.tools import assert_raises_regexp, raises
from nose.tools import assert_raises_regex, raises
import warnings
import mock
import tempfile
Expand Down Expand Up @@ -203,7 +203,7 @@ def test_bngl_import_expected_errors():

for filename, errmsg in expected_errors.items():
full_filename = _bngl_location(filename)
yield (assert_raises_regexp,
yield (assert_raises_regex,
BnglImportError,
errmsg,
bngl_import_compare_simulations,
Expand Down

0 comments on commit b053005

Please sign in to comment.