diff --git a/.github/workflows/test_pypi.yml b/.github/workflows/test_pypi.yml index 4f3533850f..68675c578a 100644 --- a/.github/workflows/test_pypi.yml +++ b/.github/workflows/test_pypi.yml @@ -11,7 +11,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.9", "3.10", "3.11"] + python-version: ["3.9", "3.10", "3.11", "3.12"] os: [ubuntu-22.04, macos-latest] runs-on: ${{ matrix.os }} diff --git a/.github/workflows/test_python_ver_matrix.yml b/.github/workflows/test_python_ver_matrix.yml index 866a3fc0f7..9290cd0c1a 100644 --- a/.github/workflows/test_python_ver_matrix.yml +++ b/.github/workflows/test_python_ver_matrix.yml @@ -25,7 +25,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ['3.9', '3.10', '3.11'] + python-version: ['3.9', '3.10', '3.11', '3.12'] experimental: [false] steps: @@ -44,15 +44,27 @@ jobs: - name: Install apt dependencies uses: ./.github/actions/install-apt-dependencies - # install AMICI - name: Build BNGL run: scripts/buildBNGL.sh + - name: Install python package run: scripts/installAmiciSource.sh + # until https://github.com/dateutil/dateutil >2.8.2 is released https://github.com/dateutil/dateutil/issues/1314 + - run: source build/venv/bin/activate && pip3 install git+https://github.com/dateutil/dateutil.git@296d419fe6bf3b22897f8f210735ac9c4e1cb796 + if: matrix.python-version == '3.12' + + # install pysb before sympy to allow for sympy>=1.12 (https://github.com/pysb/pysb/commit/e83937cb8c74afc9b2fa96595b68464946745f33) + - run: source build/venv/bin/activate && pip3 install git+https://github.com/pysb/pysb + + # until sympy>1.12 is released + - run: source build/venv/bin/activate && pip3 install git+https://github.com/sympy/sympy.git@master + if: matrix.python-version == '3.12' + - name: Python tests run: | source build/venv/bin/activate \ - && pip3 install git+https://github.com/pysb/pysb \ - && python3 -m pytest --ignore-glob=*petab* \ + && python3 -m pytest \ + --durations=10 \ + --ignore-glob=*petab* \ --ignore-glob=*test_splines.py ${AMICI_DIR}/python/tests diff --git a/python/sdist/amici/logging.py b/python/sdist/amici/logging.py index 2648fc5b28..df39c4a219 100644 --- a/python/sdist/amici/logging.py +++ b/python/sdist/amici/logging.py @@ -34,24 +34,24 @@ def _setup_logger( level: Optional[int] = logging.WARNING, console_output: Optional[bool] = True, file_output: Optional[bool] = False, - capture_warnings: Optional[bool] = True, + capture_warnings: Optional[bool] = False, ) -> logging.Logger: """ - Set up a new logging.Logger for AMICI logging + Set up a new :class:`logging.Logger` for AMICI logging. :param level: - Logging level, typically using a constant like logging.INFO or - logging.DEBUG + Logging level, typically using a constant like :obj:`logging.INFO` or + :obj:`logging.DEBUG` :param console_output: - Set up a default console log handler if True (default) + Set up a default console log handler if ``True`` (default) :param file_output: Supply a filename to copy all log output to that file, or - set to False to disable (default) + set to ``False`` to disable (default) :param capture_warnings: - Capture warnings from Python's warnings module if True (default) + Capture warnings from Python's warnings module if ``True`` :return: A :class:`logging.Logger` object for AMICI logging. Note that other @@ -81,7 +81,12 @@ def _setup_logger( log.setLevel(level) + py_warn_logger = logging.getLogger("py.warnings") + # Remove default logging handler + for handler in log.handlers: + if handler in py_warn_logger.handlers: + py_warn_logger.removeHandler(handler) log.handlers = [] log_fmt = logging.Formatter( @@ -105,7 +110,10 @@ def _setup_logger( log.debug("Python version: %s", platform.python_version()) log.debug("Hostname: %s", socket.getfqdn()) - logging.captureWarnings(capture_warnings) + if capture_warnings: + logging.captureWarnings(capture_warnings) + for handler in log.handlers: + py_warn_logger.addHandler(handler) return log diff --git a/python/sdist/amici/sbml_import.py b/python/sdist/amici/sbml_import.py index b6a7b37ed4..124dfc7a63 100644 --- a/python/sdist/amici/sbml_import.py +++ b/python/sdist/amici/sbml_import.py @@ -2776,15 +2776,17 @@ def replace_logx(math_str: Union[str, float, None]) -> Union[str, float, None]: return re.sub(r"(^|\W)log(\d+)\(", r"\g<1>1/ln(\2)*ln(", math_str) -def _collect_event_assignment_parameter_targets(sbml_model: sbml.Model): - targets = set() +def _collect_event_assignment_parameter_targets( + sbml_model: sbml.Model, +) -> list[sp.Symbol]: + targets = [] sbml_parameters = sbml_model.getListOfParameters() sbml_parameter_ids = [p.getId() for p in sbml_parameters] for event in sbml_model.getListOfEvents(): for event_assignment in event.getListOfEventAssignments(): target_id = event_assignment.getVariable() if target_id in sbml_parameter_ids: - targets.add( + targets.append( _get_identifier_symbol( sbml_parameters[sbml_parameter_ids.index(target_id)] )