Hi Dave,
We're seeing this error in our CI in libNeuroML in the pull request there:
https://github.com/NeuralEnsemble/libNeuroML/pull/110
The complete trace is:
self = <neuroml.test.test_hdf5_optimized.TestNeuroMLHDF5Optimized testMethod=test_write_load>
def test_write_load(self):
# for f in []:
# for f in ['complete.nml']:
# for f in ['simplenet.nml','testh5.nml','MediumNet.net.nml','complete.nml']:
for f in ["simplenet.nml", "MediumNet.net.nml"]:
file_name = "%s/../examples/test_files/%s" % (self.base_dir, f)
print("Loading %s" % file_name)
nml_doc0 = loaders.read_neuroml2_file(file_name, include_includes=True)
summary0 = nml_doc0.summary()
print(summary0)
nml_h5_file = "%s/../examples/tmp/%s__1.h5" % (self.base_dir, f)
writers.NeuroMLHdf5Writer.write(nml_doc0, nml_h5_file)
print("Written to: %s" % nml_h5_file)
nml_doc1 = loaders.read_neuroml2_file(
nml_h5_file, include_includes=True, optimized=True
)
summary1 = nml_doc1.summary().replace(" (optimized)", "")
print("\n" + summary1)
compare(summary0, summary1)
nml_h5_file_2 = "%s/../examples/tmp/%s__2.h5" % (self.base_dir, f)
writers.NeuroMLHdf5Writer.write(nml_doc1, nml_h5_file_2)
print("Written to: %s" % nml_h5_file_2)
# exit()
> nml_doc2 = loaders.read_neuroml2_file(nml_h5_file_2, include_includes=True)
neuroml/test/test_hdf5_optimized.py:60:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
neuroml/loaders.py:214: in read_neuroml2_file
optimized=optimized,
neuroml/loaders.py:270: in _read_neuroml2
nml2_doc = NeuroMLHdf5Loader.load(nml2_file_name_or_string, optimized=optimized)
neuroml/loaders.py:57: in load
doc = cls.__nml2_doc(src, optimized)
neuroml/loaders.py:87: in __nml2_doc
currParser.parse(file_name)
neuroml/hdf5/NeuroMLHdf5Parser.py:144: in parse
self.parse_group(h5file.root.neuroml)
neuroml/hdf5/NeuroMLHdf5Parser.py:188: in parse_group
self.parse_group(node)
neuroml/hdf5/NeuroMLHdf5Parser.py:179: in parse_group
self.parse_group(node)
neuroml/hdf5/NeuroMLHdf5Parser.py:170: in parse_group
self.start_group(g)
neuroml/hdf5/NeuroMLHdf5Parser.py:601: in start_group
properties=properties,
neuroml/hdf5/NetworkBuilder.py:74: in handle_population
self.nml_doc.append(component_obj)
neuroml/nml/nml.py:39122: in append
self.add(element)
neuroml/nml/nml.py:14599: in add
self.__add(obj, targets[0], force)
neuroml/nml/nml.py:14654: in __add
obj, member.get_name()
neuroml/nml/nml.py:223: in __str__
namespacedef_=settings["str_namespacedefs"],
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <neuroml.nml.nml.IafCell object at 0x7f5037247a50>
outfile = <_io.StringIO object at 0x7f5036851950>, level = 0
namespaceprefix_ = '', namespacedef_ = '', name_ = None, pretty_print = True
def export(
self,
outfile,
level,
namespaceprefix_="",
namespacedef_="",
name_="IafCell",
pretty_print=True,
):
imported_ns_def_ = GenerateDSNamespaceDefs_.get("IafCell")
if imported_ns_def_ is not None:
namespacedef_ = imported_ns_def_
if pretty_print:
eol_ = "\n"
else:
eol_ = ""
if self.original_tagname_ is not None and name_ == "IafCell":
name_ = self.original_tagname_
if UseCapturedNS_ and self.ns_prefix_:
namespaceprefix_ = self.ns_prefix_ + ":"
showIndent(outfile, level, pretty_print)
outfile.write(
"<%s%s%s"
% (
namespaceprefix_,
name_,
> namespacedef_ and " " + namespacedef_ or "",
)
)
E TypeError: unicode argument expected, got 'str'
neuroml/nml/nml.py:45392: TypeError
nml.py was generated on Python 3.10.0 with generateDS.py version 2.40.5. The schema file is here:
The generated nml.py file is here:
The helper_methods and so on are in the same folder there. We use this script to generate nml.py and the format it with black:
We only get this error on Python 2.7. It does not happen on any of the Python 3 versions.
Cheers,
Ankur
Ankur,
Thanks for your help with this.
What I've done so far:
Downloaded
NeuroML_v2.2.xsd,helper_methods.py, andregenerate-nml.sh.Modified
regenerate-nml.shfor my environment: path togenerateDS.py, name of XML schema file.Ran
regenerate-nml.sh-- generatednml.py.Build a virtual environment with Python 2.7.18, then installed
lxml, andsixrequired bygenerateDS.Next -- I need to run the new
nml.pyagainst an XML instancedocument so that it generates the reported exception.
I looked in the
libNeuroMLGit repo, but could not find an XML instance file.Do you have one I could use to generate the error?
I'll pick this up again on Monday.
In the meantime, I hope you have an enjoyable weekend.
Dave
OK, I've found a number of examples (
*.nml) here:https://github.com/NeuroML/NeuroML2/tree/master/examples.
But, the ones I have tried so far do not cause an exception, either
with Python 3.9.7 nor with Python 2.7.18. The ones I've tried are:
For example, it displays exported output when I run this:
By the way, I'm running
nml.pywith Python 2.7.18, but Igenerated
nml.pywith Python 3.9.7.Dave
Hi Dave,
Thanks for that. I'll go through the failing test and see if I can narrow it down. If you're not seeing the error, it could be something else in the library that's using nml.py perhaps. I'll report back once I have something.
Thanks again,
Ankur
Hi Dave,
I haven't been able to pin point the cause of the error yet but I did find a workaround that fixes the issue for us:
https://github.com/NeuralEnsemble/libNeuroML/pull/110/commits/aa025c608a678697d14acaca1cf8d7ed0a0a7fd6
The error is caused when we use nml.py with other bits, like reading from HDF5 files, so I'm thinking it's caused by some code in our HDF5 related methods where we haven't been careful enough to take both Python 2 and 3 into account.
So we'll just carry this tweak for the time being, and we expect to drop Python 2 support after the next release and won't run into this issue in the future then.
Please close this issue
Cheers,
Ankur
Hi Dave,
I think I figured out what was going on. In the generated
nml.pyfile, in the__str__method ofGeneratedsSuper, we're initialising a newoutputvariable as an object of theStringIOclass. At the moment, we simplyfrom io import StringIO, which while works for Python 3, isn't the rightStringIOto use for Python 2. In Python 2, for strings, we must useStringIO.StringIObecause there,io.StringIOis for unicode strings. So, I think the generateds.py code should be tweaked as per this diff:I've manually made the change in
nml.pyfor the moment, and all our tests now pass correctly on both Python2 and Python3.https://github.com/NeuralEnsemble/libNeuroML/commit/fcdcd56af1ded448696f009d041a3aa2183b81a8
A simple reproducer is:
With the version of
nml.pygenerated from generateds, it'll throw an error for Python 2 but not for Python 3:With the tweak, it'll work correctly for both.
I wasn't aware of this difference between
StringIO.StringIOandio.StringIOin Python 2, but this clarified it:What do you think? Does this look correct now?
Thanks again for all your help and patience,
Ankur
Ankur,
Your fix looks good to me. I've applied that patch, did some testing, created a new version, and uploaded it to PyPI and SourceForge.net.
Thanks for your help with this. Please let me know if/when there is another issue.
Dave