diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9c3e6557..3974c21a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + python-version: ["3.10", "3.11", "3.12"] fail-fast: false steps: diff --git a/pyneuroml/neuron/analysis/HHanalyse.py b/pyneuroml/neuron/analysis/HHanalyse.py index 2e5acbc2..c771222d 100644 --- a/pyneuroml/neuron/analysis/HHanalyse.py +++ b/pyneuroml/neuron/analysis/HHanalyse.py @@ -4,17 +4,18 @@ Implementation of the pynml-modchananalysis command """ -import typing import argparse import logging import re import subprocess import sys from math import log +from typing import Optional import matplotlib.pyplot as pylab import neuron from pylab import * + from pyneuroml.utils import get_state_color from pyneuroml.utils.cli import build_namespace @@ -137,7 +138,7 @@ def remove_comments(txt): return clear_txt -def get_states(txt: str) -> typing.List[str]: +def get_states(txt: str) -> list[str]: """Get list of states from mod file text. :param txt: mod file text @@ -157,7 +158,7 @@ def get_states(txt: str) -> typing.List[str]: return state_list -def get_suffix(txt: str) -> typing.Optional[str]: +def get_suffix(txt: str) -> Optional[str]: """Get suffix mod file text :param txt: mod file text diff --git a/pyneuroml/utils/misc.py b/pyneuroml/utils/misc.py index 98d22bb3..2afd481c 100644 --- a/pyneuroml/utils/misc.py +++ b/pyneuroml/utils/misc.py @@ -7,7 +7,6 @@ Copyright 2024 NeuroML contributors """ - import os from pyneuroml import JNEUROML_VERSION @@ -25,3 +24,23 @@ def get_path_to_jnml_jar() -> str: "jNeuroML-%s-jar-with-dependencies.jar" % JNEUROML_VERSION, ) return jar_path + + +try: + from contextlib import chdir # Python 3.11+ +except ImportError: + from contextlib import contextmanager + + @contextmanager + def chdir(path): + """chdir context manager for python < 3.11 + + :param path: path to change to + :type path: str or os.PathLike + """ + prev_cwd = os.getcwd() + os.chdir(path) + try: + yield + finally: + os.chdir(prev_cwd) diff --git a/setup.cfg b/setup.cfg index c5dc1441..4e20cfca 100644 --- a/setup.cfg +++ b/setup.cfg @@ -32,7 +32,7 @@ install_requires = graphviz typing; python_version<"3.5" lxml - numpy<2.0.0 + numpy sympy ppft[dill] diff --git a/tests/neuron/test_neuron_utils.py b/tests/neuron/test_neuron_utils.py index 8afb10b6..9b855643 100644 --- a/tests/neuron/test_neuron_utils.py +++ b/tests/neuron/test_neuron_utils.py @@ -7,34 +7,31 @@ Copyright 2023 NeuroML contributors """ - -import unittest import logging -import tempfile -import pytest import pathlib +import tempfile +import unittest +import pytest from pyneuroml.neuron import ( - load_hoc_or_python_file, - morphinfo, + export_mod_to_neuroml2, get_utils_hoc, getinfo, - export_mod_to_neuroml2, + load_hoc_or_python_file, + morphinfo, ) from . import load_olm_cell - logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) class TestNeuronUtils(unittest.TestCase): - """Test Neuron Utils""" - def test_hoc_loader(self): + def test_hoc_loader1(self): """Test hoc loader util function""" with tempfile.NamedTemporaryFile(mode="w", suffix=".hoc") as f: print( @@ -47,6 +44,7 @@ def test_hoc_loader(self): self.assertTrue(load_hoc_or_python_file(f.name)) + def test_hoc_loader2(self): with tempfile.NamedTemporaryFile(mode="w", suffix=".hoc") as f: print( """ @@ -56,8 +54,10 @@ def test_hoc_loader(self): flush=True, ) - self.assertFalse(load_hoc_or_python_file(f.name)) + with self.assertRaises(RuntimeError): + load_hoc_or_python_file(f.name) + def test_hoc_loader3(self): # loading python files is not yet implemented with tempfile.NamedTemporaryFile(mode="w", suffix=".py") as f: print( diff --git a/tests/plot/test_morphology_plot.py b/tests/plot/test_morphology_plot.py index 81cadad2..7f907df0 100644 --- a/tests/plot/test_morphology_plot.py +++ b/tests/plot/test_morphology_plot.py @@ -20,9 +20,7 @@ plot_2D_schematic, plot_segment_groups_curtain_plots, ) -from pyneuroml.plot.PlotMorphologyPlotly import ( - plot_3D_cell_morphology_plotly, -) +from pyneuroml.plot.PlotMorphologyPlotly import plot_3D_cell_morphology_plotly from pyneuroml.plot.PlotMorphologyVispy import ( create_cylindrical_mesh, make_cell_upright, @@ -31,6 +29,7 @@ plot_interactive_3D, ) from pyneuroml.pynml import read_neuroml2_file +from pyneuroml.utils.misc import chdir from .. import BaseTestCase @@ -41,13 +40,18 @@ class TestMorphologyPlot(BaseTestCase): """Test Plot module""" + @pytest.fixture(autouse=True) + def plot_dir(self, monkeypatch, request): + target_dir = request.path.parent + monkeypatch.chdir(target_dir) + def test_2d_point_plotter(self): """Test plot_2D_point_cells function.""" - nml_files = ["tests/plot/Izh2007Cells.net.nml"] + nml_files = ["Izh2007Cells.net.nml"] for nml_file in nml_files: ofile = pl.Path(nml_file).name for plane in ["xy"]: - filename = f"tests/plot/test_morphology_plot_2d_point_{ofile.replace('.', '_', 100)}_{plane}.png" + filename = f"test_morphology_plot_2d_point_{ofile.replace('.', '_', 100)}_{plane}.png" # remove the file first try: pl.Path(filename).unlink() @@ -62,17 +66,17 @@ def test_2d_point_plotter(self): @pytest.mark.localonly def test_3d_point_plotter(self): """Test plot_2D_point_cells function.""" - nml_files = ["tests/plot/Izh2007Cells.net.nml"] + nml_files = ["Izh2007Cells.net.nml"] for nml_file in nml_files: plot_interactive_3D(nml_file, theme="dark", nogui=True) def test_2d_plotter(self): """Test plot_2D function.""" - nml_files = ["tests/plot/Cell_497232312.cell.nml", "tests/plot/test.cell.nml"] + nml_files = ["Cell_497232312.cell.nml", "test.cell.nml"] for nml_file in nml_files: ofile = pl.Path(nml_file).name for plane in ["yz"]: - filename = f"tests/plot/test_morphology_plot_2d_{ofile.replace('.', '_', 100)}_{plane}.png" + filename = f"test_morphology_plot_2d_{ofile.replace('.', '_', 100)}_{plane}.png" # remove the file first try: pl.Path(filename).unlink() @@ -86,13 +90,13 @@ def test_2d_plotter(self): def test_2d_morphology_plotter_data_overlay(self): """Test plot_2D_cell_morphology method with data.""" - nml_files = ["tests/plot/Cell_497232312.cell.nml"] + nml_files = ["Cell_497232312.cell.nml"] for nml_file in nml_files: nml_doc = read_neuroml2_file(nml_file) cell: neuroml.Cell = nml_doc.cells[0] ofile = pl.Path(nml_file).name plane = "xy" - filename = f"tests/plot/test_morphology_plot_2d_{ofile.replace('.', '_', 100)}_{plane}_with_data.png" + filename = f"test_morphology_plot_2d_{ofile.replace('.', '_', 100)}_{plane}_with_data.png" # remove the file first try: pl.Path(filename).unlink() @@ -119,183 +123,198 @@ def test_2d_morphology_plotter_data_overlay(self): def test_2d_plotter_network_with_spec(self): """Test plot_2D function with a network of a few cells with specs.""" - nml_file = "tests/plot/L23-example/TestNetwork.net.nml" - ofile = pl.Path(nml_file).name - # percentage - for plane in ["zx"]: - filename = f"test_morphology_plot_2d_spec_{ofile.replace('.', '_', 100)}_{plane}.png" - # remove the file first - try: - pl.Path(filename).unlink() - except FileNotFoundError: - pass + with chdir("L23-example/"): + nml_file = "TestNetwork.net.nml" + ofile = pl.Path(nml_file).name + # percentage + for plane in ["zx"]: + filename = f"test_morphology_plot_2d_spec_{ofile.replace('.', '_', 100)}_{plane}.png" + # remove the file first + try: + pl.Path(filename).unlink() + except FileNotFoundError: + pass - plot_2D( - nml_file, - nogui=True, - plane2d=plane, - save_to_file=filename, - plot_spec={"point_fraction": 0.5}, - ) + plot_2D( + nml_file, + nogui=True, + plane2d=plane, + save_to_file=filename, + plot_spec={"point_fraction": 0.5}, + ) - self.assertIsFile(filename) - pl.Path(filename).unlink() + self.assertIsFile(filename) + pl.Path(filename).unlink() def test_2d_plotter_network_with_detailed_spec(self): - nml_file = "tests/plot/L23-example/TestNetwork.net.nml" - ofile = pl.Path(nml_file).name - # more detailed plot_spec - for plane in ["xy"]: - filename = f"test_morphology_plot_2d_spec_{ofile.replace('.', '_', 100)}_{plane}.png" - # remove the file first - try: - pl.Path(filename).unlink() - except FileNotFoundError: - pass + with chdir("L23-example/"): + nml_file = "TestNetwork.net.nml" + ofile = pl.Path(nml_file).name + # more detailed plot_spec + for plane in ["xy"]: + filename = f"test_morphology_plot_2d_spec_{ofile.replace('.', '_', 100)}_{plane}.png" + # remove the file first + try: + pl.Path(filename).unlink() + except FileNotFoundError: + pass - plot_2D( - nml_file, - nogui=True, - plane2d=plane, - save_to_file=filename, - plot_spec={ - "point_cells": ["HL23VIP"], - "detailed_cells": ["HL23PYR"], - "schematic_cells": ["HL23PV"], - "constant_cells": ["HL23SST"], - }, - ) - self.assertIsFile(filename) - pl.Path(filename).unlink() + plot_2D( + nml_file, + nogui=True, + plane2d=plane, + save_to_file=filename, + plot_spec={ + "point_cells": ["HL23VIP"], + "detailed_cells": ["HL23PYR"], + "schematic_cells": ["HL23PV"], + "constant_cells": ["HL23SST"], + }, + ) + self.assertIsFile(filename) + pl.Path(filename).unlink() def test_2d_plotter_network(self): """Test plot_2D function with a network of a few cells.""" - nml_file = "tests/plot/L23-example/TestNetwork.net.nml" - ofile = pl.Path(nml_file).name - for plane in ["yz"]: - filename = f"tests/plot/test_morphology_plot_2d_{ofile.replace('.', '_', 100)}_{plane}.png" - # remove the file first - try: - pl.Path(filename).unlink() - except FileNotFoundError: - pass + with chdir("L23-example/"): + nml_file = "TestNetwork.net.nml" + ofile = pl.Path(nml_file).name + for plane in ["yz"]: + filename = f"test_morphology_plot_2d_{ofile.replace('.', '_', 100)}_{plane}.png" + # remove the file first + try: + pl.Path(filename).unlink() + except FileNotFoundError: + pass - plot_2D(nml_file, nogui=True, plane2d=plane, save_to_file=filename) + plot_2D(nml_file, nogui=True, plane2d=plane, save_to_file=filename) - self.assertIsFile(filename) - # pl.Path(filename).unlink() + self.assertIsFile(filename) + pl.Path(filename).unlink() def test_2d_constant_plotter_network(self): """Test plot_2D_schematic function with a network of a few cells.""" - nml_file = "tests/plot/L23-example/TestNetwork.net.nml" - ofile = pl.Path(nml_file).name - for plane in ["xz"]: - filename = f"tests/plot/test_morphology_plot_2d_{ofile.replace('.', '_', 100)}_{plane}_constant.png" - # remove the file first - try: - pl.Path(filename).unlink() - except FileNotFoundError: - pass + with chdir("L23-example/"): + nml_file = "TestNetwork.net.nml" + ofile = pl.Path(nml_file).name + for plane in ["xz"]: + filename = f"test_morphology_plot_2d_{ofile.replace('.', '_', 100)}_{plane}_constant.png" + # remove the file first + try: + pl.Path(filename).unlink() + except FileNotFoundError: + pass - plot_2D( - nml_file, - nogui=True, - plane2d=plane, - save_to_file=filename, - plot_type="constant", - ) + plot_2D( + nml_file, + nogui=True, + plane2d=plane, + save_to_file=filename, + plot_type="constant", + ) - self.assertIsFile(filename) - pl.Path(filename).unlink() + self.assertIsFile(filename) + pl.Path(filename).unlink() def test_2d_schematic_plotter_network(self): """Test plot_2D_schematic function with a network of a few cells.""" - nml_file = "tests/plot/L23-example/TestNetwork.net.nml" - ofile = pl.Path(nml_file).name - for plane in ["xy"]: - filename = f"tests/plot/test_morphology_plot_2d_{ofile.replace('.', '_', 100)}_{plane}_schematic.png" - # remove the file first - try: - pl.Path(filename).unlink() - except FileNotFoundError: - pass + with chdir("L23-example/"): + nml_file = "TestNetwork.net.nml" + ofile = pl.Path(nml_file).name + for plane in ["xy"]: + filename = f"test_morphology_plot_2d_{ofile.replace('.', '_', 100)}_{plane}_schematic.png" + # remove the file first + try: + pl.Path(filename).unlink() + except FileNotFoundError: + pass - plot_2D( - nml_file, - nogui=True, - plane2d=plane, - save_to_file=filename, - plot_type="schematic", - ) + plot_2D( + nml_file, + nogui=True, + plane2d=plane, + save_to_file=filename, + plot_type="schematic", + ) - self.assertIsFile(filename) - pl.Path(filename).unlink() + self.assertIsFile(filename) + pl.Path(filename).unlink() @pytest.mark.localonly def test_3d_schematic_plotter(self): """Test plot_3D_schematic plotter function.""" - nml_file = "tests/plot/L23-example/HL23PYR.cell.nml" - nml_doc = read_neuroml2_file(nml_file) - cell: neuroml.Cell = nml_doc.cells[0] - plot_3D_schematic( - cell, - segment_groups=None, - nogui=True, - ) + with chdir("L23-example/"): + nml_file = "HL23PYR.cell.nml" + nml_doc = read_neuroml2_file(nml_file) + cell: neuroml.Cell = nml_doc.cells[0] + plot_3D_schematic( + cell, + segment_groups=None, + nogui=True, + ) @pytest.mark.localonly def test_3d_morphology_plotter_vispy_network(self): """Test plot_3D_cell_morphology_vispy function.""" - nml_file = "tests/plot/L23-example/TestNetwork.net.nml" - plot_interactive_3D(nml_file, min_width=1, nogui=True, theme="dark") + with chdir("L23-example/"): + nml_file = "TestNetwork.net.nml" + plot_interactive_3D(nml_file, min_width=1, nogui=True, theme="dark") @pytest.mark.localonly def test_3d_morphology_plotter_vispy_network_with_spec(self): """Test plot_3D_cell_morphology_vispy function.""" - nml_file = "tests/plot/L23-example/TestNetwork.net.nml" - plot_interactive_3D( - nml_file, - min_width=1, - nogui=True, - theme="dark", - plot_spec={"point_fraction": 0.5}, - ) + with chdir("L23-example/"): + nml_file = "TestNetwork.net.nml" + plot_interactive_3D( + nml_file, + min_width=1, + nogui=True, + theme="dark", + plot_spec={"point_fraction": 0.5}, + ) @pytest.mark.localonly def test_3d_morphology_plotter_vispy_network_with_spec2(self): """Test plot_3D_cell_morphology_vispy function.""" - nml_file = "tests/plot/L23-example/TestNetwork.net.nml" - plot_interactive_3D( - nml_file, - min_width=1, - nogui=True, - theme="dark", - plot_spec={ - "point_cells": ["HL23VIP"], - "detailed_cells": ["HL23PYR"], - "schematic_cells": ["HL23PV"], - "constant_cells": ["HL23SST"], - }, - ) + with chdir("L23-example/"): + nml_file = "TestNetwork.net.nml" + plot_interactive_3D( + nml_file, + min_width=1, + nogui=True, + theme="dark", + plot_spec={ + "point_cells": ["HL23VIP"], + "detailed_cells": ["HL23PYR"], + "schematic_cells": ["HL23PV"], + "constant_cells": ["HL23SST"], + }, + ) @pytest.mark.localonly def test_3d_plotter_vispy_morph_only(self): """Test plot_interactive_3D function with morphology only NeuroML document.""" - nml_file = "tests/plot/L23-example/HL23VIP.morph.cell.nml" - plot_interactive_3D(nml_file) + with chdir("L23-example/"): + nml_file = "HL23VIP.morph.cell.nml" + plot_interactive_3D(nml_file) @pytest.mark.localonly def test_3d_plotter_vispy(self): """Test plot_3D_cell_morphology_vispy function.""" - nml_file = "tests/plot/L23-example/HL23PYR.cell.nml" - nml_doc = read_neuroml2_file(nml_file) - cell: neuroml.Cell = nml_doc.cells[0] - plot_3D_cell_morphology( - cell=cell, nogui=True, color="Groups", verbose=True, plot_type="constant" - ) + with chdir("L23-example/"): + nml_file = "HL23PYR.cell.nml" + nml_doc = read_neuroml2_file(nml_file) + cell: neuroml.Cell = nml_doc.cells[0] + plot_3D_cell_morphology( + cell=cell, + nogui=True, + color="Groups", + verbose=True, + plot_type="constant", + ) # test a circular soma - nml_file = "tests/plot/test-spherical-soma.cell.nml" + nml_file = "test-spherical-soma.cell.nml" nml_doc = read_neuroml2_file(nml_file) cell: neuroml.Cell = nml_doc.cells[0] plot_3D_cell_morphology( @@ -304,12 +323,10 @@ def test_3d_plotter_vispy(self): def test_3d_plotter_plotly(self): """Test plot_3D_cell_morphology_plotly function.""" - nml_files = ["tests/plot/Cell_497232312.cell.nml", "tests/plot/test.cell.nml"] + nml_files = ["Cell_497232312.cell.nml", "test.cell.nml"] for nml_file in nml_files: ofile = pl.Path(nml_file).name - filename = ( - f"tests/plot/test_morphology_plot_3d_{ofile.replace('.', '_', 100)}.png" - ) + filename = f"test_morphology_plot_3d_{ofile.replace('.', '_', 100)}.png" # remove the file first try: pl.Path(filename).unlink() @@ -323,8 +340,8 @@ def test_3d_plotter_plotly(self): def test_2d_schematic_plotter(self): """Test plot_2D_schematic function.""" - nml_file = "tests/plot/Cell_497232312.cell.nml" - olm_file = "tests/plot/test.cell.nml" + nml_file = "Cell_497232312.cell.nml" + olm_file = "test.cell.nml" nml_doc = read_neuroml2_file(nml_file) cell: neuroml.Cell = nml_doc.cells[0] @@ -336,7 +353,9 @@ def test_2d_schematic_plotter(self): for plane in ["xy", "yz", "xz"]: # olm cell - filename = f"tests/plot/test_schematic_plot_2d_{olm_ofile.replace('.', '_', 100)}_{plane}.png" + filename = ( + f"test_schematic_plot_2d_{olm_ofile.replace('.', '_', 100)}_{plane}.png" + ) try: pl.Path(filename).unlink() except FileNotFoundError: @@ -351,7 +370,9 @@ def test_2d_schematic_plotter(self): ) # more complex cell - filename = f"tests/plot/test_schematic_plot_2d_{ofile.replace('.', '_', 100)}_{plane}.png" + filename = ( + f"test_schematic_plot_2d_{ofile.replace('.', '_', 100)}_{plane}.png" + ) # remove the file first try: pl.Path(filename).unlink() @@ -372,14 +393,14 @@ def test_2d_schematic_plotter(self): def test_plot_segment_groups_curtain_plots(self): """Test plot_segment_groups_curtain_plots function.""" - nml_file = "tests/plot/Cell_497232312.cell.nml" + nml_file = "Cell_497232312.cell.nml" nml_doc = read_neuroml2_file(nml_file) cell: neuroml.Cell = nml_doc.cells[0] ofile = pl.Path(nml_file).name # more complex cell - filename = f"tests/plot/test_curtain_plot_2d_{ofile.replace('.', '_', 100)}.png" + filename = f"test_curtain_plot_2d_{ofile.replace('.', '_', 100)}.png" # remove the file first try: pl.Path(filename).unlink() @@ -402,14 +423,14 @@ def test_plot_segment_groups_curtain_plots(self): def test_plot_segment_groups_curtain_plots_with_data(self): """Test plot_segment_groups_curtain_plots function with data overlay.""" - nml_file = "tests/plot/Cell_497232312.cell.nml" + nml_file = "Cell_497232312.cell.nml" nml_doc = read_neuroml2_file(nml_file) cell: neuroml.Cell = nml_doc.cells[0] ofile = pl.Path(nml_file).name # more complex cell - filename = f"tests/plot/test_curtain_plot_2d_{ofile.replace('.', '_', 100)}_withdata.png" + filename = f"test_curtain_plot_2d_{ofile.replace('.', '_', 100)}_withdata.png" # remove the file first try: pl.Path(filename).unlink() diff --git a/tests/plot/test_plot.py b/tests/plot/test_plot.py index fe1083fb..9c8244da 100644 --- a/tests/plot/test_plot.py +++ b/tests/plot/test_plot.py @@ -7,13 +7,15 @@ Copyright 2023 NeuroML contributors """ -import random -import pytest -import unittest import logging import pathlib as pl +import random +import unittest + +import pytest + +from pyneuroml.plot import generate_interactive_plot, generate_plot -from pyneuroml.plot import generate_plot, generate_interactive_plot from .. import BaseTestCase logger = logging.getLogger(__name__) @@ -23,10 +25,15 @@ class TestPlot(BaseTestCase): """Test Plot module""" + @pytest.fixture(autouse=True) + def this_dir(self, monkeypatch, request): + target_dir = request.path.parent + monkeypatch.chdir(target_dir) + @pytest.mark.localonly def test_generate_plot_animated(self): """Test generate_plot function.""" - filename = "tests/plot/test_generate_plot.gif" + filename = "test_generate_plot.gif" # remove the file first try: @@ -58,7 +65,7 @@ def test_generate_plot_animated(self): @pytest.mark.localonly def test_generate_plot_animated_specify_writer(self): """Test generate_plot function with specific writer.""" - filename = "tests/plot/test_generate_plot_writer.gif" + filename = "test_generate_plot_writer.gif" # remove the file first try: @@ -91,8 +98,8 @@ def test_generate_plot_animated_specify_writer(self): @pytest.mark.localonly def test_generate_plot_animated_should_default_pillow_when_writer_invalid(self): """Test generate_plot function does not fail when writer is invalid.""" - filename1 = "tests/plot/test_generate_plot_writer1.gif" - filename2 = "tests/plot/test_generate_plot_writer2.gif" + filename1 = "test_generate_plot_writer1.gif" + filename2 = "test_generate_plot_writer2.gif" # remove the file first try: @@ -145,7 +152,7 @@ def test_generate_plot_animated_should_default_pillow_when_writer_invalid(self): def test_generate_plot(self): """Test generate_plot function.""" - filename = "tests/plot/test_generate_plot.png" + filename = "test_generate_plot.png" # remove the file first try: @@ -178,7 +185,7 @@ def test_generate_plot(self): def test_generate_interactive_plot(self): """Test generate_interactive_plot function.""" - filename = "tests/plot/test_generate_interactive_plot.png" + filename = "test_generate_interactive_plot.png" # remove the file first try: diff --git a/tests/sbml/test_sbml.py b/tests/sbml/test_sbml.py index b928d240..8a1ee9fe 100755 --- a/tests/sbml/test_sbml.py +++ b/tests/sbml/test_sbml.py @@ -3,20 +3,29 @@ import os import stat +import pytest + from pyneuroml import sbml +@pytest.fixture(autouse=True) +def this_dir(monkeypatch, request): + target_dir = request.path.parent + monkeypatch.chdir(target_dir) + + def test_sbml_validate_a_valid_file(): "ensure it validates a single valid file by returning True" - fname = "tests/sbml/test_data/valid_doc.sbml" + print(f"{os.getcwd() = }") + fname = "test_data/valid_doc.sbml" result = sbml.validate_sbml_files([fname]) assert result def test_sbml_validate_missing_inputfile(): try: - sbml.validate_sbml_files(["tests/sbml/test_data/nonexistent_file"]) + sbml.validate_sbml_files(["test_data/nonexistent_file"]) except FileNotFoundError: return except Exception: @@ -26,7 +35,7 @@ def test_sbml_validate_missing_inputfile(): def test_sbml_validate_no_read_access(): - fname = "tests/sbml/test_data/no_read_access.sbml" + fname = "test_data/no_read_access.sbml" # Remove read permission os.chmod(fname, 0) @@ -65,7 +74,7 @@ def test_sbml_validate_unit_consistency_check(): try: result = sbml.validate_sbml_files( - ["tests/sbml/test_data/inconsistent_units_doc.sbml"], strict_units=True + ["test_data/inconsistent_units_doc.sbml"], strict_units=True ) assert not result except Exception: @@ -73,7 +82,7 @@ def test_sbml_validate_unit_consistency_check(): try: result = sbml.validate_sbml_files( - ["tests/sbml/test_data/inconsistent_units_doc.sbml"], strict_units=False + ["test_data/inconsistent_units_doc.sbml"], strict_units=False ) assert result except Exception: @@ -90,7 +99,7 @@ def test_sbml_validate_flag_all_invalid_files(): n_files = 3 for i in range(n_files): - fname = "tests/sbml/test_data/invalid_doc%02d.sbml" % i + fname = "test_data/invalid_doc%02d.sbml" % i try: result = sbml.validate_sbml_files([fname]) diff --git a/tests/sedml/test_sedml.py b/tests/sedml/test_sedml.py index 8a0c1a39..e7199297 100755 --- a/tests/sedml/test_sedml.py +++ b/tests/sedml/test_sedml.py @@ -3,22 +3,28 @@ import os import stat +import pytest + from pyneuroml import sedml +@pytest.fixture(autouse=True) +def this_dir(monkeypatch, request): + target_dir = request.path.parent + monkeypatch.chdir(target_dir) + + def test_sedml_validate_a_valid_file(): "ensure it validates a single valid file by returning True" - fname = "tests/sedml/test_data/valid_doc.sedml" + fname = "test_data/valid_doc.sedml" result = sedml.validate_sedml_files([fname]) assert result def test_sedml_validate_missing_sourcefile(): try: - result = sedml.validate_sedml_files( - ["tests/sedml/test_data/missing_model_source.sedml"] - ) + result = sedml.validate_sedml_files(["test_data/missing_model_source.sedml"]) assert not result return except Exception: @@ -29,7 +35,7 @@ def test_sedml_validate_missing_sourcefile(): def test_sedml_validate_missing_inputfile(): try: - sedml.validate_sedml_files(["tests/sedml/test_data/nonexistent_file"]) + sedml.validate_sedml_files(["test_data/nonexistent_file"]) except FileNotFoundError: return except Exception: @@ -39,7 +45,7 @@ def test_sedml_validate_missing_inputfile(): def test_sedml_validate_no_read_access(): - fname = "tests/sedml/test_data/no_read_access.sedml" + fname = "test_data/no_read_access.sedml" # Remove read permission os.chmod(fname, 0) @@ -80,7 +86,7 @@ def test_sedml_validate_flag_all_invalid_files(): n_files = 2 for i in range(n_files): - fname = "tests/sedml/test_data/invalid_doc%02d.sedml" % (i + 1) + fname = "test_data/invalid_doc%02d.sedml" % (i + 1) try: result = sedml.validate_sedml_files([fname]) if not result: diff --git a/tests/test_pynml.py b/tests/test_pynml.py index 72b32008..21fff8c8 100644 --- a/tests/test_pynml.py +++ b/tests/test_pynml.py @@ -13,24 +13,22 @@ import shutil import unittest -from pyneuroml.pynml import ( - execute_command_in_dir, - execute_command_in_dir_with_realtime_output, - extract_lems_definition_files, - list_exposures, - list_recording_paths_for_exposures, - run_jneuroml, - validate_neuroml2, -) +import pytest + +import pyneuroml.pynml as pynmlpynml logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) class TestJarUtils(unittest.TestCase): - """Test jNeuroML jar related functions""" + @pytest.fixture(autouse=True) + def this_dir(self, monkeypatch, request): + target_dir = request.path.parent + monkeypatch.chdir(target_dir) + def test_lems_def_files_extraction(self): """Test extraction of NeuroML2 LEMS files from jar.""" filelist = [ @@ -46,19 +44,23 @@ def test_lems_def_files_extraction(self): "Synapses.xml", ] - extraction_dir = extract_lems_definition_files() + extraction_dir = pynmlpynml.extract_lems_definition_files() newfilelist = os.listdir(extraction_dir) shutil.rmtree(extraction_dir[: -1 * len("NeuroML2CoreTypes/")]) assert sorted(filelist) == sorted(newfilelist) class TestHelperUtils(unittest.TestCase): - """Test helper utilities.""" + @pytest.fixture(autouse=True) + def this_dir(self, monkeypatch, request): + target_dir = request.path.parent + monkeypatch.chdir(target_dir) + def test_exposure_listing(self): """Test listing of exposures in NeuroML documents.""" - exps = list_exposures("tests/izhikevich_test_file.nml", "iz") + exps = pynmlpynml.list_exposures("izhikevich_test_file.nml", "iz") ctypes = {} for key, val in exps.items(): ctypes[key.type] = val @@ -75,15 +77,13 @@ def test_exposure_listing(self): def test_exposure_listing_2(self): """Test listing of exposures in NeuroML documents.""" - os.chdir("tests/") - exps = list_exposures("HH_example_net.nml") + exps = pynmlpynml.list_exposures("HH_example_net.nml") print(exps) - os.chdir("../") def test_recording_path_listing(self): """Test listing of recording paths in NeuroML documents.""" - paths = list_recording_paths_for_exposures( - "tests/izhikevich_test_file.nml", "", "IzhNet" + paths = pynmlpynml.list_recording_paths_for_exposures( + "izhikevich_test_file.nml", "", "IzhNet" ) print("\n".join(paths)) # self.assertTrue("izh2007RS0/u" in paths) @@ -91,12 +91,10 @@ def test_recording_path_listing(self): def test_recording_path_listing_2(self): """Test listing of recording paths in NeuroML documents.""" - os.chdir("tests/") - paths = list_recording_paths_for_exposures( + paths = pynmlpynml.list_recording_paths_for_exposures( "HH_example_net.nml", "hh_cell", "single_hh_cell_network" ) print("\n".join(paths)) - os.chdir("../") def test_execute_command_in_dir(self): """Test execute_command_in_dir function.""" @@ -106,7 +104,7 @@ def test_execute_command_in_dir(self): output = None retcode = None - retcode, output = execute_command_in_dir( + retcode, output = pynmlpynml.execute_command_in_dir( command, exec_in_dir, verbose=verbose, prefix=" jNeuroML >> " ) @@ -116,7 +114,7 @@ def test_execute_command_in_dir(self): command_bad = "ls non_existent_file" output = None retcode = None - retcode, output = execute_command_in_dir( + retcode, output = pynmlpynml.execute_command_in_dir( command_bad, exec_in_dir, verbose=verbose, prefix=" jNeuroML >> " ) self.assertNotEqual(retcode, 0) @@ -129,7 +127,7 @@ def test_execute_command_in_dir_with_realtime_output(self): verbose = True success = False - success = execute_command_in_dir_with_realtime_output( + success = pynmlpynml.execute_command_in_dir_with_realtime_output( command, exec_in_dir, verbose=verbose, prefix=" jNeuroML >> " ) self.assertTrue(success) @@ -137,7 +135,7 @@ def test_execute_command_in_dir_with_realtime_output(self): command_bad = "ls non_existent_file" success = True - success = execute_command_in_dir_with_realtime_output( + success = pynmlpynml.execute_command_in_dir_with_realtime_output( command_bad, exec_in_dir, verbose=verbose, prefix=" jNeuroML >> " ) self.assertFalse(success) @@ -145,32 +143,32 @@ def test_execute_command_in_dir_with_realtime_output(self): def test_run_jneuroml(self): """Test run_jneuroml""" retstat = None - retstat = run_jneuroml("-v", None, None) + retstat = pynmlpynml.run_jneuroml("-v", None, None) self.assertTrue(retstat) retstat = None - retstat = run_jneuroml("-randomflag", "", "") + retstat = pynmlpynml.run_jneuroml("-randomflag", "", "") self.assertFalse(retstat) def test_validate_neuroml2(self): """Test validate_neuroml2""" - os.chdir("tests/") retval = None - retval = validate_neuroml2("HH_example_k_channel.nml") + retval = pynmlpynml.validate_neuroml2("HH_example_k_channel.nml") self.assertTrue(retval) retval = None retstring = None - retval, retstring = validate_neuroml2( + retval, retstring = pynmlpynml.validate_neuroml2( "HH_example_k_channel.nml", return_string=True ) self.assertTrue(retval) self.assertIn("Valid against schema and all tests", retstring) - os.chdir("../") retval = None retstring = None - retval, retstring = validate_neuroml2("setup.cfg", return_string=True) + retval, retstring = pynmlpynml.validate_neuroml2( + "../setup.cfg", return_string=True + ) self.assertFalse(retval) self.assertIn("1 failed", retstring) diff --git a/tests/test_runners.py b/tests/test_runners.py index 7009003f..a5bdc75a 100644 --- a/tests/test_runners.py +++ b/tests/test_runners.py @@ -10,6 +10,8 @@ import logging import pathlib as pl +import pytest + from pyneuroml.runners import ( execute_command_in_dir, execute_multiple_in_dir, @@ -26,14 +28,20 @@ class TestRunners(BaseTestCase): """Test runners module""" + # Run in top repo dir + @pytest.fixture(autouse=True) + def top_dir(self, monkeypatch, request): + target_dir = request.path.parent.parent + monkeypatch.chdir(target_dir) + def test_generate_sim_scripts_in_folder(self): """test generate_sim_scripts_in_folder method""" thispath = pl.Path(__file__) - dirname = str(thispath.parent.parent) + topdirname = str(thispath.parent.parent) dirname = generate_sim_scripts_in_folder( engine="jneuroml_neuron", lems_file_name="LEMS_NML2_Ex5_DetCell.xml", - root_dir=dirname + "/examples/", + root_dir=topdirname + "/examples/", run_dir=str(thispath.parent), ) self.assertTrue(pl.Path(dirname).exists()) diff --git a/tests/utils/test_utils.py b/tests/utils/test_utils.py index a53e6476..5b038429 100644 --- a/tests/utils/test_utils.py +++ b/tests/utils/test_utils.py @@ -12,6 +12,7 @@ import pathlib as pl import neuroml +import pytest from pyneuroml.pynml import read_neuroml2_file, write_neuroml2_file from pyneuroml.utils import ( @@ -30,9 +31,14 @@ class TestUtils(BaseTestCase): """Test utils module""" + @pytest.fixture(autouse=True) + def to_test_dir(self, monkeypatch, request): + target_dir = request.path.parent.parent + monkeypatch.chdir(target_dir) + def test_extract_position_info(self): """Test extract_position_info""" - nml_files = ["tests/plot/L23-example/TestNetwork.net.nml"] + nml_files = ["plot/L23-example/TestNetwork.net.nml"] for nml_file in nml_files: nml_model = read_neuroml2_file( nml_file, @@ -156,7 +162,7 @@ def test_rotate_cell(self): ) newdoc.validate(recursive=True) - write_neuroml2_file(newdoc, "tests/utils/test_rotation.net.nml", validate=True) + write_neuroml2_file(newdoc, "utils/test_rotation.net.nml", validate=True) def test_translate_cell_to_coords(self): """Test translate_cell_to_coords""" @@ -279,6 +285,4 @@ def test_translate_cell_to_coords(self): ) newdoc.validate(recursive=True) - write_neuroml2_file( - newdoc, "tests/utils/test_translation.net.nml", validate=True - ) + write_neuroml2_file(newdoc, "utils/test_translation.net.nml", validate=True)