Skip to content

_prepare_identifiers captures custom function metadata but loses the implementation : makes export useless for models with custom functions #81

@Sanchit2662

Description

@Sanchit2662

Summary

While going through the baseexport code I noticed that _prepare_identifiers in helper.py does not serialize the actual implementation of custom Function objects. It only captures the metadata argument units, argument types, return unit, return type and completely ignores the function body.
So if I have something like this:

from brian2 import *
                                                                                                                                                                                  
@check_units(x=volt, result=volt)                                                                                                                                               
def my_nonlinearity(x):                                                                                                                                                       
      return clip(x, 0*mV, 100*mV)                                                                                                                                              

G = NeuronGroup(10, 'dv/dt = my_nonlinearity(v) / (10*ms) : volt', method='euler')
The exported dictionary for my_nonlinearity looks like:

  {                                                                                                                                                                             
      'type': 'custom_func',
      'arg_units': [volt],
      'arg_types': ['float'],                                                                                                                                                         
      'return_unit': volt,
      'return_type': 'float'                                                                                                                                                    
  }

The function name appears in the equation string, the metadata is there, but the actual implementation is gone. Anyone trying to reconstruct this network from the export has no idea what my_nonlinearity does they just know it takes a volt and returns a volt.

This is a direct blocker for the basicimporter I'm planning to implement (see issue #78). If the export doesn't carry the function body, the importer cannot reconstruct any model that uses a custom function.


Proposed fix

When the identifier is a Function with a Python implementation available, serialize the source via inspect.getsource(value.pyfunc) and store it alongside the metadata:

import inspect
                                                                                                                                                                                  
clean_identifiers.update({key: {                                                                                                                                                    
      'type': 'custom_func',
      'arg_units': value._arg_units,                                                                                                                                            
      'arg_types': value._arg_types,
      'return_unit': value._return_unit,                                                                                                                                              
      'return_type': value._return_type,
      'source_code': inspect.getsource(value.pyfunc)  # add this                                                                                                                
  }})                                                                                                                                                                             

For cases where source is not available (C++ implementations, lambdas defined in a REPL) inspect.getsource will raise in that case we store a warning marker so the importer knows the function is present but not reconstructable, rather than silently missing it.


Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions