mirror of
https://github.com/nasa/trick.git
synced 2024-12-18 20:57:55 +00:00
* Fix for assigning to non-existent variables (#1708) This fix modifies Trick's convert_swig script. It adds a directive to not accept dynamic attributes. The directive will ensure that modelers do not assign to non-existent parameter in their input files. The prior fix (issues #1288 and/or #1603) did not cover C structures, so this commit is really an addendum to that fix. With this commit, the convert_swig script will generate a non-dynamic directive foreach class and structure. This fix also stops generating swig interface code for typedef structure definitions since swig only produces an interface to the actual typedef name. For example, with this typedef: typedef struct StructureName { double main_engine_thrust; /* N Thrust of main engine */ struct StructureName* next; /* ** Next pointer */ } TypeDefName; swig creates an interface for "TypeDefName", and not "StructureName", so there is no need for Trick to produce anything in regards "StructureName". * Fix for issue with classes defined in ifndef SWIG block convert_swig takes in the raw header and does no preprocessing, so blocks of c/c++ header code which are meant to be skipped by Swig are processed by convert_swig. This causes an issue with the generated python code that try to access classes that are ifndef SWIGed out. To fix this, check for class existence in the generated python code e.g: if 'MomMom' in globals(): MomMom.__setattr__ = _swig_setattr_nondynamic_instance_variable(object.__setattr__) * Fix for assignment to swig_double and swig_int primitives The previous commit(s) on this branch fixed bad assignments like (misspell position an attribute of BSTATE_IN): ball.state.input.positiaaaan = 4.0 This commit fixes bad assignments to leaf/primitive attributes like (try to add attribute to primitive/leaf double type): ball.state.input.position.fred = 4.0 * Moved _swig_setattr_nondynamic_instance_variable to right after each class in process_class and removed duplicate _swig_setattr_nondynamic_instance_variable blocks for classes that are not in a namespace. * Add the call for __setattr__ for class templates. --------- Co-authored-by: Hong Chen <hong.chen-1@nasa.gov>
This commit is contained in:
parent
f666708374
commit
f2e93ac490
@ -337,6 +337,24 @@ sub process_file() {
|
|||||||
print OUT "\n$new_contents" ;
|
print OUT "\n$new_contents" ;
|
||||||
print OUT "$contents\n" ;
|
print OUT "$contents\n" ;
|
||||||
print OUT $global_template_typedefs ;
|
print OUT $global_template_typedefs ;
|
||||||
|
|
||||||
|
# Add _swig_setattr_nondynamic_instance_variable function for raising AttributeError for improper non-class attribute assingment in input processor.
|
||||||
|
# _swig_setattr_nondynamic_instance_variable function is added for each class in process_class subroutine.
|
||||||
|
foreach my $c ( @class_names ) {
|
||||||
|
if ( ! exists $class_typemap_printed{$c} ) {
|
||||||
|
my $c_ = $c ;
|
||||||
|
$c_ =~ s/\:/_/g ;
|
||||||
|
if ( $c !~ /::/ ) {
|
||||||
|
print OUT "\n#if SWIG_VERSION > 0x040000\n";
|
||||||
|
print OUT "%pythoncode %{\n" ;
|
||||||
|
print OUT " if '$c' in globals():\n";
|
||||||
|
print OUT " $c.__setattr__ = _swig_setattr_nondynamic_instance_variable(object.__setattr__)\n" ;
|
||||||
|
print OUT "%}\n" ;
|
||||||
|
print OUT "#endif\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Add a trick_cast_as macro line for each class parsed in the file. These lines must appear at the bottom of the
|
# Add a trick_cast_as macro line for each class parsed in the file. These lines must appear at the bottom of the
|
||||||
# file to ensure they are not in a namespace directive and they are after the #define statements they depend on.
|
# file to ensure they are not in a namespace directive and they are after the #define statements they depend on.
|
||||||
undef %class_typemap_printed ;
|
undef %class_typemap_printed ;
|
||||||
@ -479,6 +497,9 @@ sub process_template($$) {
|
|||||||
my ( $contents_ref , $new_contents_ref ) = @_ ;
|
my ( $contents_ref , $new_contents_ref ) = @_ ;
|
||||||
my $extracted ;
|
my $extracted ;
|
||||||
|
|
||||||
|
# Add _swig_setattr_nondynamic_instance_variable function for raising AttributeError for improper class attribute assingment in input processor
|
||||||
|
# The function call is inserted after the 1st { of the class template so it is placed at the top
|
||||||
|
$$contents_ref=~s/{\n/{\n\n#if SWIG_VERSION > 0x040000\n\%pythoncode \%{\n __setattr__ = _swig_setattr_nondynamic_instance_variable(object.__setattr__)\n\%}\n#endif\n/m;
|
||||||
if ( $$contents_ref =~ s/^(\s*;)//s ) {
|
if ( $$contents_ref =~ s/^(\s*;)//s ) {
|
||||||
$$new_contents_ref .= $1 ;
|
$$new_contents_ref .= $1 ;
|
||||||
} else {
|
} else {
|
||||||
@ -605,6 +626,9 @@ sub process_class($$$$$) {
|
|||||||
$class_content .= $1 ;
|
$class_content .= $1 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Add _swig_setattr_nondynamic_instance_variable function for raising AttributeError for improper class attribute assingment in input processor
|
||||||
|
$class_content .= "\n#if SWIG_VERSION > 0x040000\n\%pythoncode \%{\n __setattr__ = _swig_setattr_nondynamic_instance_variable(object.__setattr__)\n\%}\n#endif\n" ;
|
||||||
|
|
||||||
($extracted, $$contents_ref) = extract_bracketed( "{" . $$contents_ref , "{}") ;
|
($extracted, $$contents_ref) = extract_bracketed( "{" . $$contents_ref , "{}") ;
|
||||||
|
|
||||||
# remove the trailing semicolon because we may append text to the class.
|
# remove the trailing semicolon because we may append text to the class.
|
||||||
@ -709,7 +733,6 @@ sub process_class($$$$$) {
|
|||||||
push @$class_names_ref , "$curr_namespace$class_name" ;
|
push @$class_names_ref , "$curr_namespace$class_name" ;
|
||||||
|
|
||||||
# write the class contents and semicolon to ensure any template declarations below are after the semicolon.
|
# write the class contents and semicolon to ensure any template declarations below are after the semicolon.
|
||||||
$class_content .= "\n#if SWIG_VERSION > 0x040000\n\%pythoncode \%{\n __setattr__ = _swig_setattr_nondynamic_instance_variable(object.__setattr__)\n\%}\n#endif\n" ;
|
|
||||||
$class_content .= $extracted . ";\n" ;
|
$class_content .= $extracted . ";\n" ;
|
||||||
|
|
||||||
my $c_ = "$curr_namespace$class_name" ;
|
my $c_ = "$curr_namespace$class_name" ;
|
||||||
@ -756,7 +779,7 @@ sub process_typedef_struct($$$$) {
|
|||||||
my ($typedef_struct_string , $contents_ref, $new_contents_ref , $class_names_ref) = @_ ;
|
my ($typedef_struct_string , $contents_ref, $new_contents_ref , $class_names_ref) = @_ ;
|
||||||
|
|
||||||
my $extracted ;
|
my $extracted ;
|
||||||
my ($begin, $tail , $struct_names, @struct_names) ;
|
my ($tail , $struct_names, @struct_names) ;
|
||||||
|
|
||||||
#print "*** typedef_struct_string = $typedef_struct_string ***\n" ;
|
#print "*** typedef_struct_string = $typedef_struct_string ***\n" ;
|
||||||
|
|
||||||
@ -765,7 +788,6 @@ sub process_typedef_struct($$$$) {
|
|||||||
$typedef_struct_string =~ s/((?:typedef\s+)?(struct|union)\s* # the words typedef struct|union
|
$typedef_struct_string =~ s/((?:typedef\s+)?(struct|union)\s* # the words typedef struct|union
|
||||||
([_A-Za-z]\w*)?\s* # optional name
|
([_A-Za-z]\w*)?\s* # optional name
|
||||||
{)//sx ;
|
{)//sx ;
|
||||||
$begin = $3 ;
|
|
||||||
|
|
||||||
($extracted, $$contents_ref) = extract_bracketed( "{" . $$contents_ref , "{}") ;
|
($extracted, $$contents_ref) = extract_bracketed( "{" . $$contents_ref , "{}") ;
|
||||||
#print "*** extracted = $extracted ***\n" ;
|
#print "*** extracted = $extracted ***\n" ;
|
||||||
@ -780,9 +802,6 @@ sub process_typedef_struct($$$$) {
|
|||||||
$struct_names =~ s/\s//g ;
|
$struct_names =~ s/\s//g ;
|
||||||
@struct_names = split /,/ , $struct_names ;
|
@struct_names = split /,/ , $struct_names ;
|
||||||
|
|
||||||
if ( $begin ne "" ) {
|
|
||||||
push @$class_names_ref , $begin ;
|
|
||||||
}
|
|
||||||
foreach my $s ( @struct_names ) {
|
foreach my $s ( @struct_names ) {
|
||||||
if ( $s !~ /\*/ ) {
|
if ( $s !~ /\*/ ) {
|
||||||
push @$class_names_ref , $s ;
|
push @$class_names_ref , $s ;
|
||||||
|
@ -66,3 +66,19 @@ class swig_double {
|
|||||||
PyObject * __len__() ;
|
PyObject * __len__() ;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
%pythoncode %{
|
||||||
|
#if SWIG_VERSION > 0x040000
|
||||||
|
def _trick_setattr_nondynamic_instance_variable(set):
|
||||||
|
def set_instance_attr(self, name, value):
|
||||||
|
if name == "thisown":
|
||||||
|
self.this.own(value)
|
||||||
|
elif name == "this":
|
||||||
|
set(self, name, value)
|
||||||
|
else:
|
||||||
|
msg = f'You cannot add instance attribute \'{name}\' to Trick swig_double'
|
||||||
|
raise AttributeError(msg)
|
||||||
|
return set_instance_attr
|
||||||
|
|
||||||
|
swig_double.__setattr__ = _trick_setattr_nondynamic_instance_variable(object.__setattr__)
|
||||||
|
#endif
|
||||||
|
%}
|
||||||
|
@ -89,3 +89,19 @@ class swig_int {
|
|||||||
PyObject * __bool__() ;
|
PyObject * __bool__() ;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
%pythoncode %{
|
||||||
|
#if SWIG_VERSION > 0x040000
|
||||||
|
def _trick_setattr_nondynamic_instance_variable(set):
|
||||||
|
def set_instance_attr(self, name, value):
|
||||||
|
if name == "thisown":
|
||||||
|
self.this.own(value)
|
||||||
|
elif name == "this":
|
||||||
|
set(self, name, value)
|
||||||
|
else:
|
||||||
|
msg = f'You cannot add instance attribute \'{name}\' to Trick swig_int'
|
||||||
|
raise AttributeError(msg)
|
||||||
|
return set_instance_attr
|
||||||
|
|
||||||
|
swig_int.__setattr__ = _trick_setattr_nondynamic_instance_variable(object.__setattr__)
|
||||||
|
#endif
|
||||||
|
%}
|
||||||
|
Loading…
Reference in New Issue
Block a user