• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nasa / trick / 16529262532

25 Jul 2025 06:44PM UTC coverage: 55.922% (+0.03%) from 55.895%
16529262532

Pull #1930

github

web-flow
Merge e688aa7db into d3daa8e16
Pull Request #1930: Add capability to save input file used during run #1928

5 of 9 new or added lines in 2 files covered. (55.56%)

5 existing lines in 3 files now uncovered.

12338 of 22063 relevant lines covered (55.92%)

262577.33 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

65.93
/trick_source/sim_services/InputProcessor/IPPython.cpp
1
/*
2
   PURPOSE: ( Python input processor )
3
   REFERENCE: ( Trick Simulation Environment )
4
   ASSUMPTIONS AND LIMITATIONS: ( None )
5
   CLASS: ( N/A )
6
   LIBRARY DEPENDENCY: ( None )
7
   PROGRAMMERS: ( Alex Lin NASA 2009 )
8
*/
9

10
#include <Python.h>
11
#include <iostream>
12
#include <sstream>
13
#include <vector>
14
#include <string>
15
#include <stdlib.h>
16
#include <unistd.h>
17
#include <string.h>
18
#include <stdio.h>
19

20
#include "trick/IPPython.hh"
21
#include "trick/MemoryManager.hh"
22
#include "trick/exec_proto.hh"
23
#include "trick/exec_proto.h"
24
#include "trick/message_proto.h"
25

26
Trick::IPPython * the_pip ;
27

28
//Constructor
29
Trick::IPPython::IPPython() : Trick::InputProcessor::InputProcessor() , units_conversion_msgs(true) {
182✔
30
    the_pip = this ;
182✔
31
    return ;
182✔
32
}
33

34

35
// Need to save the state of the main thread to allow child threads to run PyRun variants.
36
static PyThreadState *_save = NULL;
37

38
/**
39
@details
40
-# Loops through all of the memorymanager allocations testing if a name handle was given.
41
 -# If a name and a user type_name were given to the allocation
42
  -# If the user_type_name is not a Trick core class, prefixed with "Trick::"
43
  -# Create a python statement to assign the python name to an address: <name> = trick.castAsTYPE(int(<address>))
44
  -# Run the statement in the python interpreter
45
*/
46
void Trick::IPPython::get_TMM_named_variables() {
191✔
47
    //std::cout << "top level names at initialization" << std::endl ;
48
    Trick::ALLOC_INFO_MAP_ITER aim_it ;
191✔
49
    for ( aim_it = trick_MM->alloc_info_map_begin() ; aim_it != trick_MM->alloc_info_map_end() ; ++aim_it ) {
5,933✔
50
        ALLOC_INFO * alloc_info = (*aim_it).second ;
5,742✔
51
        if ( alloc_info->name != NULL and alloc_info->user_type_name != NULL ) {
5,742✔
52
            std::stringstream ss ;
9,856✔
53
            std::string user_type_name = alloc_info->user_type_name ;
14,784✔
54
            size_t start_colon ;
55
            while ( ( start_colon = user_type_name.find("::") ) != std::string::npos ) {
5,513✔
56
                user_type_name.replace( start_colon , 2 , "__" ) ;
585✔
57
            }
58
            // The castAs method may not exist if the class was hidden from SWIG (#ifndef SWIG).
59
            // Use a try/except block to test if the method exists or not.  If it doesn't exist
60
            // don't worry about it.  Also only assign python variable if it is pointing to
61
            // something python doesn't owns.  Otherwise we could free the object we're trying to assign.
62
            ss << "try:" << std::endl ;
4,928✔
63
            ss << "    if '" << alloc_info->name << "' not in globals() or " ;
4,928✔
64
            ss << alloc_info->name << ".thisown == False:" <<  std::endl ;
4,928✔
65
            ss << "        " << alloc_info->name << " = " ;
4,928✔
66
            ss << "trick.castAs" << user_type_name << "(int(" << alloc_info->start << "))" << std::endl ;
4,928✔
67
            ss << "except AttributeError:" << std::endl ;
4,928✔
68
            ss << "    pass" << std::endl ;
4,928✔
69
            PyGILState_STATE gstate = PyGILState_Ensure();
4,928✔
70
            PyRun_SimpleString(ss.str().c_str()) ;
4,928✔
71
            PyGILState_Release(gstate);
4,928✔
72
        }
73
    }
74
}
191✔
75

76
bool Trick::IPPython::get_units_conversion_msgs() {
×
77
    return units_conversion_msgs ;
×
78
}
79

80
void Trick::IPPython::shoot_the_units_conversion_messenger(bool onoff) {
×
81
    if ( onoff ) {
×
82
        message_publish(MSG_WARNING, "Units conversion messages can no longer be suppressed.\n") ;
×
83
    }
84
}
×
85

86
//Initialize and run the Python input processor on the user input file.
87
int Trick::IPPython::init() {
182✔
88
    /** @par Detailed Design: */
89

90
    FILE *input_fp ;
91
    int ret ;
92
    std::string error_message ;
364✔
93

94
    // Run Py_Initialze first for python 2.x
95
#if PY_VERSION_HEX < 0x03000000
96
    Py_Initialize();
97
#endif
98

99
    /* Run the Swig generated routine in S_source_wrap.cpp. */
100
    init_swig_modules() ;
182✔
101

102
    // Run Py_Initialze after init_swig_modules for python 3.x
103
#if PY_VERSION_HEX >= 0x03000000
104
    Py_Initialize();
182✔
105
#endif
106

107
    // The following PyRun_ calls do not require the PyGILState guards because no threads are launched 
108
    /* Import simulation specific routines into interpreter. */
109
    PyRun_SimpleString(
182✔
110
     "import sys\n"
111
     "import os\n"
112
     "import struct\n"
113
     "import binascii\n"
114
     "sys.path.append(os.getcwd() + '/trick.zip')\n"
115
     "sys.path.append(os.path.join(os.environ['TRICK_HOME'], 'share/trick/pymods'))\n"
116
     "sys.path += map(str.strip, os.environ['TRICK_PYTHON_PATH'].split(':'))\n"
117
     "import trick\n"
118
     "sys.path.append(os.getcwd() + \"/Modified_data\")\n"
119
    ) ;
120

121
    /* Make shortcut names for all known sim_objects. */
122
    get_TMM_named_variables() ;
182✔
123

124
    /* An input file is not required, if the name is empty just return. */
125
    if ( input_file.empty() ) {
182✔
126
        return(0) ;
×
127
    }
128

129
    if ((input_fp = fopen(input_file.c_str(), "r")) == NULL) {
182✔
130
        error_message = "No input file found named " + input_file ;
×
131
        exec_terminate_with_return(-1 , __FILE__ , __LINE__ , error_message.c_str() ) ;
×
132
    }
133

134
    /* Read and parse the input file. */
135
    if ( verify_input ) {
182✔
136
        PyRun_SimpleString("sys.settrace(trick.traceit)") ;
×
137
    }
138

139
    /* Read and parse the input file. */
140
    if ( save_input ) {
182✔
NEW
141
        PyRun_SimpleString("trick.open_input_file_log()") ;
×
NEW
142
        PyRun_SimpleString("sys.settrace(trick.traceittofile)") ;
×
143
    }
144

145
    if ( (ret = PyRun_SimpleFile(input_fp, input_file.c_str())) !=  0 ) {
182✔
146
        exec_terminate_with_return(ret , __FILE__ , __LINE__ , "Input Processor error\n" ) ;
×
147
    }
148

149
    if ( verify_input ) {
180✔
150
       std::stringstream ss ;
×
151
       ss << "import hashlib" << std::endl ;
×
152
       ss << "input_file = " << "'" << input_file.c_str() << "'" << std::endl;
×
153
       ss << "print('{0} SHA1: {1}'.format(input_file,hashlib.sha1(open(input_file, 'rb').read()).hexdigest()))" << std::endl ;
×
154
       PyRun_SimpleString(ss.str().c_str()) ;
×
155
       exec_terminate_with_return(ret , __FILE__ , __LINE__ , "Input file verification complete\n" ) ;
×
156
    }
157

158
    if ( save_input ) {
180✔
NEW
159
       PyRun_SimpleString("trick.close_input_file_log()") ;
×
160
    }
161

162
    fclose(input_fp) ;
180✔
163

164
    // Release the GIL from the main thread.
165
    Py_UNBLOCK_THREADS
180✔
166

167
    return(0) ;
180✔
168
}
169

170
//Command to parse the given string.
171
int Trick::IPPython::parse(std::string in_string) {
141✔
172

173
    int ret ;
174
    in_string += "\n" ;
141✔
175
    PyGILState_STATE gstate = PyGILState_Ensure();
141✔
176
    ret = PyRun_SimpleString(in_string.c_str()) ;
141✔
177
    PyGILState_Release(gstate);
141✔
178

179
    return ret ;
141✔
180

181
}
182

183
/**
184
 @details
185
 The incoming statement is assumed to be a conditional fragment, i.e. "a > b".  We need
186
 to get the return value of this fragment by setting the return value of it to a known
187
 variable name in the input processor.  We can then assign that return value to the
188
 incoming return_value reference.
189

190
-# Lock the input processor mutex
191
-# Create a complete statement that assigns the conditional fragment to our return value
192
-# parse the condition
193
-# copy the return value to the incoming cond_return_value
194
-# Unlock the input processor mutex
195
*/
196
int Trick::IPPython::parse_condition(std::string in_string, int & cond_return_val ) {
45✔
197

198
    in_string =  std::string("trick_ip.ip.return_val = ") + in_string + "\n" ;
45✔
199
    // Running the simple string will set return_val.
200
    PyGILState_STATE gstate = PyGILState_Ensure();
45✔
201
    int py_ret = PyRun_SimpleString(in_string.c_str()) ;
45✔
202
    PyGILState_Release(gstate);
45✔
203
    cond_return_val = return_val ;
45✔
204

205
    return py_ret ;
45✔
206

207
}
208

209
//Restart job that reloads event_list from checkpointable structures
210
int Trick::IPPython::restart() {
9✔
211
    /* Make shortcut names for all known sim_objects. */
212
    get_TMM_named_variables() ;
9✔
213
    return 0 ;
9✔
214
}
215

216
int Trick::IPPython::shutdown() {
150✔
217

218
    if ( Py_IsInitialized() ) {
150✔
219
        // Obtain the GIL so that we can shut down properly
220
        Py_BLOCK_THREADS
150✔
221
        Py_Finalize();
150✔
222
    }
223
    return(0) ;
150✔
224
}
225

226
//TODO: remove units conversion messenger routines in 2021
227
void shoot_the_units_conversion_messenger() {
×
228
    message_publish(MSG_WARNING, "shoot_the_units_conversion_messenger() is deprecated\n") ;
×
229
    the_pip->shoot_the_units_conversion_messenger(true) ;
×
230
}
×
231

232
void revive_the_units_conversion_messenger() {
×
233
    message_publish(MSG_WARNING, "revive_the_units_conversion_messenger() is deprecated\n") ;
×
234
    the_pip->shoot_the_units_conversion_messenger(false) ;
×
235
}
×
236

237
int check_units_conversion_messenger_for_signs_of_life() {
×
238
    message_publish(MSG_WARNING, "check_units_conversion_messenger_for_signs_of_life() is deprecated\n") ;
×
239
    return the_pip->get_units_conversion_msgs() ;
×
240
}
241
//END TODO:
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc