Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add NEST 2 stage to CI #720

Merged
merged 17 commits into from
Feb 11, 2022
Merged

Add NEST 2 stage to CI #720

merged 17 commits into from
Feb 11, 2022

Conversation

clinssen
Copy link
Contributor

Combines to_nest() and install_nest() NESTML API functions into a single generate_target(), thereby fixing #503.

Introduces the concept of an abstract base class, Builder, analogous to CodeGenerator.

Adds NEST 2.20.2 integration test to CI.

@clinssen clinssen added this to the NESTML 5.0 milestone Jan 17, 2022
@clinssen clinssen requested a review from med-ayssar January 17, 2022 08:02
@clinssen clinssen linked an issue Jan 17, 2022 that may be closed by this pull request
Copy link
Contributor

@med-ayssar med-ayssar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the installation path of nest is constant, wouldn't better to set the default path without having the user explicitly calling those nest functions to extract the path?

pynestml/codegeneration/builder.py Outdated Show resolved Hide resolved
from pynestml.codegeneration.nest_builder import NESTBuilder
return NESTBuilder(target_name, options)

return None # no builder requested or available
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't be better to throw an error, so that we make sure if we have builder or not.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's alright if there is a code generator (like for .rst documents) that doesn't have a build stage.

if k in self.__class__._default_options:
self._options[k] = options[k]
else:
print("Warning: Option \"" + str(k) + "\" does not exist in code generator")

def get_option(self, k):
return self._options[k]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the following would be better: self._options.get(k, None), in case if the dictionary doesn't contain the key.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather it throw an exception. What if there exists a known key but with value None?

@tfardet
Copy link

tfardet commented Jan 17, 2022

I'm fairly suprised with this change of to_nest to generate_target that's going to break all existing code.
Is there a plan for NESTML to support other platforms than NEST?
If not I'd really advise to reconsider this: repeatedly breaking backward compatibility tends to discourage users.
Given that it does not say anywhere that NESTML API is unstable and that we've been advertising NESTML for years now, people would (understandably) expect it to be stable.

@clinssen
Copy link
Contributor Author

Since the installation path of nest is constant, wouldn't better to set the default path without having the user explicitly calling those nest functions to extract the path?

I like this idea, because it means that we don't have to explicitly pass nest_path in the code generation opts of every single call to generate_target(). Because we should avoid for NESTML to import nest anywhere outside of the tests, I'll implement this as a single external Python script that just does import nest; print(nest.ll_api.sli_func("statusdict/prefix ::")), then call this script in nest_codegenerator.py while capturing stdout.

I'm fairly suprised with this change of to_nest to generate_target that's going to break all existing code. Is there a plan for _NEST_ML to support other platforms than NEST? If not I'd really advise to reconsider this: repeatedly breaking backward compatibility tends to discourage users. Given that it does not say anywhere that NESTML API is unstable and that we've been advertising NESTML for years now, people would (understandably) expect it to be stable.

I agree completely that API changes should be kept to a minimum, but we have a growing number of code generation targets: due to evolution of the NEST API, we now even have two NEST code generators (for major versions 2 and 3); there is also "audodoc" for generating model documentation, "spinnaker" is hopefully coming soon, and I am secretly planning a minimal self-contained Python code generation option for debugging purposes.

These changes are still very flexible and up for discussion, for example, the following may or may not be true:

  • Generating code without building it is not useful, so we don't need separate calls for that, just one "generate_and_build": generate_target()
  • All code generator-specific options should go into the codegen_opts dictionary. For instance, SpiNNaker (or other non-NEST code generators) might not have any notion of a "module", so perhaps the parameter module_name should also go into codegen_opts.

I will create an issue to create a transition guide for NESTML 4 → 5, which will document the changes and how to adapt scripts.

@tfardet
Copy link

tfardet commented Jan 18, 2022

I agree completely that API changes should be kept to a minimum, but we have a growing number of code generation targets: due to evolution of the NEST API, we now even have two NEST code generators (for major versions 2 and 3); there is also "audodoc" for generating model documentation, "spinnaker" is hopefully coming soon, and I am secretly planning a minimal self-contained Python code generation option for debugging purposes.

This sound like very different targets and use cases, I'd rather have separate functions rather than an argument. It should also make it easier for new people to find them and understand their logic.

These changes are still very flexible and up for discussion, for example, the following may or may not be true:

* Generating code without building it is not useful, so we don't need separate calls for that, just one "generate_and_build": `generate_target()`

It can probably be useful when making new models, for debugging, and generally for user to understand what the NESTML code does, but probably minor, yes.

* All code generator-specific options should go into the `codegen_opts` dictionary. For instance, SpiNNaker (or other non-NEST code generators) might not have any notion of a "module", so perhaps the parameter `module_name` should also go into `codegen_opts`.

Again, I really think this screams "separate functions".

@@ -481,11 +481,7 @@ void {{neuronName}}::handle(nest::DataLoggingRequest& e)
{% if has_spike_input %}
void {{neuronName}}::handle(nest::SpikeEvent &e)
{
#if NEST2_COMPAT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was changed some time around NEST 2.18. @jougs: which NEST2 version(s) do we want to support here, does it make sense to retain support for older versions of NEST 2 (that is, older than 2.20.2)?

doc/running.rst Outdated Show resolved Hide resolved
pynestml/codegeneration/builder.py Show resolved Hide resolved
pynestml/codegeneration/builder.py Outdated Show resolved Hide resolved
pynestml/codegeneration/nest2_code_generator.py Outdated Show resolved Hide resolved
doc/running.rst Outdated Show resolved Hide resolved
pynestml/codegeneration/nest_code_generator.py Outdated Show resolved Hide resolved
pynestml/codegeneration/nest_code_generator.py Outdated Show resolved Hide resolved
} // namespace

#endif /* #ifndef {{synapseName.upper()}}_H */
{%- include "common/SynapseHeader.h.jinja2" %}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it doesn't include new changes, why is it being moved to a different place

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to support NEST2 compatibility, so the template in common can be included from the NEST3 templates directory, or from the NEST2 templates directory.

pynestml/frontend/pynestml_frontend.py Outdated Show resolved Hide resolved
pynestml/frontend/pynestml_frontend.py Show resolved Hide resolved
if k in self.__class__._default_options:
self._options[k] = options[k]
else:
print("Option \"" + str(k) + "\" does not exist in builder")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it ok to just print that one of the given keys doesn't exist in the _default_options without throwing an error?

doc/running.rst Outdated Show resolved Hide resolved
pynestml/codegeneration/nest_code_generator.py Outdated Show resolved Hide resolved
pynestml/codegeneration/nest_code_generator.py Outdated Show resolved Hide resolved
pynestml/frontend/pynestml_frontend.py Show resolved Hide resolved
tests/vector_code_generator_test.py Outdated Show resolved Hide resolved
.github/workflows/nestml-build.yml Show resolved Hide resolved
"""
generate_target(input_path, target_path, target_platform="NEST", logging_level=logging_level,
module_name=module_name, store_log=store_log, suffix=suffix, install_path=install_path,
dev=dev, codegen_opts=codegen_opts)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the call to add_libraries_to_sli missing here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's in the NESTBuilder class.

target_path = FrontendConfiguration.get_target_path()
install_path = FrontendConfiguration.get_install_path()
if install_path is not None:
add_libraries_to_sli(install_path)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this cause Circular dependency

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is that? It seems to work OK.

subprocess.check_call(make_all_cmd, stderr=subprocess.STDOUT, shell=shell,
cwd=str(os.path.join(target_path)))
except subprocess.CalledProcessError as e:
raise GeneratedCodeBuildException('Error occurred during \'make all\'! More detailed error messages can be found in stdout.')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the PR containing the add_libraries_to_sli has modified the exceptions:

Suggested change
raise GeneratedCodeBuildException('Error occurred during \'make all\'! More detailed error messages can be found in stdout.')
msg = "Error during 'make all'. More detailed error messages can be found in stdout."
raise GeneratedCodeBuildException(msg)

Copy link
Contributor

@pnbabu pnbabu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

@clinssen clinssen modified the milestones: NESTML 5.0, NESTML 5.0.0-rc2 Feb 11, 2022
@clinssen
Copy link
Contributor Author

Thank you for the comments and reviews!

@clinssen clinssen merged commit 868fe66 into nest:master Feb 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Merge of to_nest() and nest_install()
4 participants