diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 51e453f..e0f1980 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12" ] + python-version: [ "3.9", "3.10", "3.11", "3.12", "3.13" ] runs-on: [ubuntu-latest, macos-latest, windows-latest] exclude: - runs-on: macos-latest @@ -49,7 +49,6 @@ jobs: - name: Install package run: | python -m pip install --upgrade pip - pip install 'numpy<2.0.0' # due to lingering issues with other modules & numpy... pip install .[dev] - name: Lint with flake8 @@ -61,6 +60,7 @@ jobs: pip list - name: Run simple examples + shell: bash run: | cd examples python document.py @@ -70,6 +70,7 @@ jobs: python test.py - name: Test NeuroML examples + shell: bash run: | cd examples/neuroml2 @@ -78,6 +79,7 @@ jobs: # Note: NeuroML files will be validated with OMV below - name: Test SBML examples + shell: bash run: | cd examples/sbml @@ -126,7 +128,6 @@ jobs: # Run OMV tests on all engines cd examples omv all -V - omv list -V # list installed engines - name: Final version info diff --git a/docs/sphinx/source/api/Contributors.md b/docs/sphinx/source/api/Contributors.md index a64b613..0c5a0e5 100644 --- a/docs/sphinx/source/api/Contributors.md +++ b/docs/sphinx/source/api/Contributors.md @@ -3,7 +3,7 @@ # Modelspec contributors This page list names and Github profiles of contributors to Modelspec, listed in no particular order. -This page is generated periodically, most recently on 2025-02-05. +This page is generated periodically, most recently on 2025-04-16. - Padraig Gleeson ([@pgleeson](https://github.com/pgleeson)) - Manifest Chakalov ([@mqnifestkelvin](https://github.com/mqnifestkelvin)) diff --git a/setup.cfg b/setup.cfg index ee14113..8578d09 100644 --- a/setup.cfg +++ b/setup.cfg @@ -26,6 +26,7 @@ classifiers = Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 Programming Language :: Python :: 3.12 + Programming Language :: Python :: 3.13 Topic :: Scientific/Engineering Topic :: Software Development Typing :: Typed @@ -44,7 +45,7 @@ install_requires = typing_compat;python_version<'3.8' -python_requires = >=3.7 +python_requires = >=3.8 include_package_data = True package_dir = =src @@ -83,8 +84,8 @@ docs = dev = flake8 - pyneuroml>=0.7.2 - NeuroMLlite>=0.5.3 + pyneuroml>=1.3.15 + NeuroMLlite>=0.6.1 python-libsbml modelspec[test] pre-commit diff --git a/src/modelspec/__init__.py b/src/modelspec/__init__.py index e791326..8849e8a 100644 --- a/src/modelspec/__init__.py +++ b/src/modelspec/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.3.6" +__version__ = "0.3.7" from .base_types import Base, define, has, field, fields, optional, instance_of, in_ diff --git a/src/modelspec/base_types.py b/src/modelspec/base_types.py index 4f152ab..7b15e6c 100644 --- a/src/modelspec/base_types.py +++ b/src/modelspec/base_types.py @@ -566,9 +566,9 @@ def _is_child_field(cls, field_name: str) -> bool: # Check if the type of the field is a list or dict collection_arg = None - if get_origin(f.type) == list and len(get_args(f.type)) > 0: + if get_origin(f.type) is list and len(get_args(f.type)) > 0: collection_arg = get_args(f.type)[0] - elif get_origin(f.type) == dict and len(get_args(f.type)) > 0: + elif get_origin(f.type) is dict and len(get_args(f.type)) > 0: collection_arg = get_args(f.type)[1] try: @@ -641,16 +641,16 @@ def _is_base_type( value = get_origin(value) return ( - value == int - or value == str - or value == bool - or value == float - or (can_be_list and value == list) - or (can_be_dict and value == dict) - or (can_be_ndarray and value == numpy.ndarray) + value is int + or value is str + or value is bool + or value is float + or (can_be_list and value is list) + or (can_be_dict and value is dict) + or (can_be_ndarray and value is numpy.ndarray) or (can_be_none and value is None) or (can_be_eval_expr and cls._is_evaluable_expression(value)) - or value == Union + or value is Union ) @staticmethod @@ -671,11 +671,11 @@ def _type_to_str(type_: Any) -> str: # If its a Generic type elif get_origin(type_) is not None: - if get_origin(type_) == list and len(get_args(type_)) > 0: + if get_origin(type_) is list and len(get_args(type_)) > 0: return Base._type_to_str(get_args(type_)[0]) - elif get_origin(type_) == dict and len(get_args(type_)) > 0: + elif get_origin(type_) is dict and len(get_args(type_)) > 0: return Base._type_to_str(get_args(type_)[1]) - elif get_origin(type_) == Union and len(get_args(type_)) > 0: + elif get_origin(type_) is Union and len(get_args(type_)) > 0: return ( "Union[" + ", ".join([Base._type_to_str(arg) for arg in get_args(type_)]) @@ -916,9 +916,9 @@ def insert_links(text, format=MARKDOWN_FORMAT): table_info.append([n, t, d]) # Get the contained type - if get_origin(type_) == list and len(get_args(type_)) > 0: + if get_origin(type_) is list and len(get_args(type_)) > 0: referenced.append(get_args(type_)[0]) - elif get_origin(type_) == dict and len(get_args(type_)) > 1: + elif get_origin(type_) is dict and len(get_args(type_)) > 1: referenced.append(get_args(type_)[1]) else: referenced.append(type_) @@ -1080,7 +1080,7 @@ def _is_list_base(cl): Check if a class is a list of Base objects. These will be serialized as dicts if the underlying class has an id attribute. """ - return get_origin(cl) == list and issubclass(get_args(cl)[0], Base) + return get_origin(cl) is list and issubclass(get_args(cl)[0], Base) converter.register_unstructure_hook_factory(_is_list_base, _unstructure_list_base) diff --git a/src/modelspec/utils.py b/src/modelspec/utils.py index 4eca4fb..b6c6808 100644 --- a/src/modelspec/utils.py +++ b/src/modelspec/utils.py @@ -486,13 +486,13 @@ def evaluate( expr = tf.constant(int(expr)) else: expr = int(expr) - except: + except Exception: try: if array_format == FORMAT_TENSORFLOW: expr = tf.constant(float(expr)) else: expr = float(expr) - except: + except Exception: pass if type(expr) is list: @@ -525,7 +525,7 @@ def evaluate( else: # will have failed if not number print_(" Returning {}: {}".format(type(expr), expr), verbose) return expr - except: + except Exception: try: if rng: expr = expr.replace("random()", "rng.random()") @@ -582,12 +582,12 @@ def parse_list_like(list_str): try: expr = int(list_str) return [expr] - except: + except Exception: pass try: expr = float(list_str) return [expr] - except: + except Exception: pass if "[" in list_str: return eval(list_str) diff --git a/tests/test_utils.py b/tests/test_utils.py index 80fc991..585402b 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -19,15 +19,15 @@ def test_evaluate(self): assert evaluate("p+p", params, verbose=True) == 66 print("======") - assert type(evaluate("33")) == int - assert type(evaluate("33", cast_to_int=True)) == int - assert type(evaluate("33.0")) == float - assert type(evaluate("33.0", cast_to_int=True)) == int + assert type(evaluate("33")) is int + assert type(evaluate("33", cast_to_int=True)) is int + assert type(evaluate("33.0")) is float + assert type(evaluate("33.0", cast_to_int=True)) is int - assert type(evaluate("33.1")) == float - assert type(evaluate("33.1a", verbose=True)) == str + assert type(evaluate("33.1")) is float + assert type(evaluate("33.1a", verbose=True)) is str - assert type(evaluate("a")) == str + assert type(evaluate("a")) is str import random