Skip to content

Commit 17e9adb

Browse files
Merge pull request #413 from NeuroML/fix/406
Improve checks to ensure that the right input files are provided for each pynml command
2 parents 3a6b89d + d3e3984 commit 17e9adb

File tree

4 files changed

+216
-65
lines changed

4 files changed

+216
-65
lines changed

pyneuroml/errors.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,9 @@
1010
FILE_NOT_FOUND_ERR = 13
1111
ARGUMENT_ERR = 14
1212
UNKNOWN_ERR = 15
13+
14+
15+
class NMLFileTypeError(RuntimeError):
16+
"""A custom file type error to use for failing file checks."""
17+
18+
pass

pyneuroml/io.py

Lines changed: 88 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,27 @@
1515
import typing
1616
from typing import Optional
1717

18+
import lems.model.model as lems_model
1819
import neuroml.loaders as loaders
1920
import neuroml.writers as writers
2021
from neuroml import NeuroMLDocument
2122

22-
import lems.model.model as lems_model
23-
from pyneuroml.errors import FILE_NOT_FOUND_ERR
23+
from pyneuroml.errors import ARGUMENT_ERR, FILE_NOT_FOUND_ERR, NMLFileTypeError
2424
from pyneuroml.validators import validate_neuroml2
2525

2626
logger = logging.getLogger(__name__)
2727
logger.setLevel(logging.INFO)
2828

2929

30+
# extension: standard
31+
pynml_file_type_dict = {
32+
"xml": "LEMS",
33+
"nml": "NeuroML",
34+
"sedml": "SED-ML",
35+
"sbml": "SBML",
36+
}
37+
38+
3039
def read_neuroml2_file(
3140
nml2_file_name: str,
3241
include_includes: bool = False,
@@ -130,12 +139,12 @@ def read_neuroml2_file(
130139

131140
if fix_external_morphs_biophys:
132141
from neuroml.utils import fix_external_morphs_biophys_in_cell
142+
133143
fix_external_morphs_biophys_in_cell(nml2_doc)
134144

135145
return nml2_doc
136146

137147

138-
139148
def write_neuroml2_file(
140149
nml2_doc: NeuroMLDocument,
141150
nml2_file_name: str,
@@ -228,49 +237,98 @@ def confirm_file_exists(filename: str) -> None:
228237
sys.exit(FILE_NOT_FOUND_ERR)
229238

230239

231-
def confirm_neuroml_file(filename: str) -> None:
240+
def confirm_neuroml_file(filename: str, sys_error: bool = False) -> None:
232241
"""Confirm that file exists and is a NeuroML file before proceeding with
233242
processing.
234243
235244
:param filename: Names of files to check
236245
:type filename: str
246+
:param sys_error: toggle whether function should exit or raise exception
247+
:type sys_error: bool
237248
"""
238-
# print('Checking file: %s'%filename)
239-
# Some conditions to check if a LEMS file was entered
240-
# TODO: Ideally we'd like to check the root node: checking file extensions is brittle
241-
confirm_file_exists(filename)
242-
if filename.startswith("LEMS_"):
243-
logger.warning(
244-
textwrap.dedent(
245-
"""
246-
*************************************************************************************
247-
** Warning, you may be trying to use a LEMS XML file (containing <Simulation> etc.)
248-
** for a pyNeuroML option when a NeuroML2 file is required...
249-
*************************************************************************************
250-
"""
251-
)
252-
)
249+
error_string = textwrap.dedent(
250+
"""
251+
*************************************************************************************
252+
** You may be trying to use a LEMS XML file (containing <Simulation> etc.)
253+
** for a pyNeuroML option when a NeuroML2 file is required.
254+
*************************************************************************************
255+
"""
256+
)
257+
258+
try:
259+
confirm_file_type(filename, ["nml"])
260+
except NMLFileTypeError as e:
261+
if filename.startswith("LEMS_"):
262+
logger.warning(error_string)
263+
if sys_error is True:
264+
logger.error(e)
265+
sys.exit(ARGUMENT_ERR)
266+
else:
267+
raise e
253268

254269

255-
def confirm_lems_file(filename: str) -> None:
270+
def confirm_lems_file(filename: str, sys_error: bool = False) -> None:
256271
"""Confirm that file exists and is a LEMS file before proceeding with
257272
processing.
258273
259274
:param filename: Names of files to check
260275
:type filename: list of strings
276+
:param sys_error: toggle whether function should exit or raise exception
277+
:type sys_error: bool
261278
"""
262279
# print('Checking file: %s'%filename)
263280
# Some conditions to check if a LEMS file was entered
264281
# TODO: Ideally we'd like to check the root node: checking file extensions is brittle
282+
error_string = textwrap.dedent(
283+
"""
284+
*************************************************************************************
285+
** You may be trying to use a NeuroML2 file for a pyNeuroML option
286+
** when a LEMS XML file (containing <Simulation> etc.) is required.
287+
*************************************************************************************
288+
"""
289+
)
290+
try:
291+
confirm_file_type(filename, ["xml"])
292+
except NMLFileTypeError as e:
293+
if filename.endswith("nml"):
294+
logger.warning(error_string)
295+
if sys_error is True:
296+
logger.error(e)
297+
sys.exit(ARGUMENT_ERR)
298+
else:
299+
raise e
300+
301+
302+
def confirm_file_type(
303+
filename: str,
304+
file_exts: typing.List[str],
305+
error_str: typing.Optional[str] = None,
306+
sys_error: bool = False,
307+
) -> None:
308+
"""Confirm that a file exists and has the necessary extension
309+
310+
:param filename: filename to confirm
311+
:type filename: str
312+
:param file_exts: list of valid file extensions, without the leading dot
313+
:type file_exts: list of strings
314+
:param error_str: an optional error string to print along with the thrown
315+
exception
316+
:type error_str: string (optional)
317+
318+
:raises NMLFileTypeError: if file does not have one of the provided extensions
319+
320+
"""
265321
confirm_file_exists(filename)
266-
if filename.endswith("nml"):
267-
logger.warning(
268-
textwrap.dedent(
269-
"""
270-
*************************************************************************************
271-
** Warning, you may be trying to use a NeuroML2 file for a pyNeuroML option
272-
** when a LEMS XML file (containing <Simulation> etc.) is required...
273-
*************************************************************************************
274-
"""
275-
)
322+
filename_ext = filename.split(".")[-1]
323+
file_types = [f"{x} ({pynml_file_type_dict[x]})" for x in file_exts]
324+
if filename_ext not in file_exts:
325+
error_string = (
326+
f"Expected file extension(s): {', '.join(file_types)}; got {filename_ext}"
276327
)
328+
if error_str is not None:
329+
error_string += "\n" + error_str
330+
if sys_error is True:
331+
logger.error(error_string)
332+
sys.exit(ARGUMENT_ERR)
333+
else:
334+
raise NMLFileTypeError(error_string)

0 commit comments

Comments
 (0)