1818import lems .model .model as lems_model
1919import neuroml .loaders as loaders
2020import neuroml .writers as writers
21+ from lxml import etree
2122from neuroml import NeuroMLDocument
2223
2324from pyneuroml .errors import ARGUMENT_ERR , FILE_NOT_FOUND_ERR , NMLFileTypeError
2728logger .setLevel (logging .INFO )
2829
2930
30- # extension: standard
31- pynml_file_type_dict = {
32- "xml" : "LEMS" ,
33- "nml" : "NeuroML" ,
34- "sedml" : "SED-ML" ,
35- "sbml" : "SBML" ,
36- }
37-
38-
3931def read_neuroml2_file (
4032 nml2_file_name : str ,
4133 include_includes : bool = False ,
@@ -256,7 +248,7 @@ def confirm_neuroml_file(filename: str, sys_error: bool = False) -> None:
256248 )
257249
258250 try :
259- confirm_file_type (filename , ["nml" ])
251+ confirm_file_type (filename , ["nml" ], "neuroml" )
260252 except NMLFileTypeError as e :
261253 if filename .startswith ("LEMS_" ):
262254 logger .warning (error_string )
@@ -276,9 +268,6 @@ def confirm_lems_file(filename: str, sys_error: bool = False) -> None:
276268 :param sys_error: toggle whether function should exit or raise exception
277269 :type sys_error: bool
278270 """
279- # print('Checking file: %s'%filename)
280- # Some conditions to check if a LEMS file was entered
281- # TODO: Ideally we'd like to check the root node: checking file extensions is brittle
282271 error_string = textwrap .dedent (
283272 """
284273 *************************************************************************************
@@ -288,7 +277,7 @@ def confirm_lems_file(filename: str, sys_error: bool = False) -> None:
288277 """
289278 )
290279 try :
291- confirm_file_type (filename , ["xml" ])
280+ confirm_file_type (filename , ["xml" ], "lems" )
292281 except NMLFileTypeError as e :
293282 if filename .endswith ("nml" ):
294283 logger .warning (error_string )
@@ -302,15 +291,22 @@ def confirm_lems_file(filename: str, sys_error: bool = False) -> None:
302291def confirm_file_type (
303292 filename : str ,
304293 file_exts : typing .List [str ],
294+ root_tag : typing .Optional [str ] = None ,
305295 error_str : typing .Optional [str ] = None ,
306296 sys_error : bool = False ,
307297) -> None :
308- """Confirm that a file exists and has the necessary extension
298+ """Confirm that a file exists and is of the provided type.
299+
300+ First we rely on file extensions to test for type, since this is the
301+ simplest way. If this test fails, we read the full file and test the root
302+ tag if one has been provided.
309303
310304 :param filename: filename to confirm
311305 :type filename: str
312306 :param file_exts: list of valid file extensions, without the leading dot
313307 :type file_exts: list of strings
308+ :param root_tag: root tag for file, used if extensions do not match
309+ :type root_tag: str
314310 :param error_str: an optional error string to print along with the thrown
315311 exception
316312 :type error_str: string (optional)
@@ -320,11 +316,32 @@ def confirm_file_type(
320316 """
321317 confirm_file_exists (filename )
322318 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 } "
327- )
319+
320+ matched = False
321+
322+ if filename_ext in file_exts :
323+ matched = True
324+
325+ got_root_tag = None
326+
327+ if matched is False :
328+ if root_tag is not None :
329+ with open (filename ) as i_file :
330+ xml_tree = etree .parse (i_file )
331+ tree_root = xml_tree .getroot ()
332+ got_root_tag = tree_root .tag
333+
334+ if got_root_tag .lower () == root_tag .lower ():
335+ matched = True
336+
337+ if matched is False :
338+ error_string = f"Expected file extension does not match: { ', ' .join (file_exts )} ; got { filename_ext } ."
339+
340+ if root_tag is not None :
341+ error_string += (
342+ f" Expected root tag does not match: { root_tag } ; got { got_root_tag } "
343+ )
344+
328345 if error_str is not None :
329346 error_string += "\n " + error_str
330347 if sys_error is True :
0 commit comments