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

nasa / trick / 25456501308

06 May 2026 07:29PM UTC coverage: 55.935% (-0.8%) from 56.7%
25456501308

Pull #2011

github

web-flow
Merge 7ad262960 into 7054e405e
Pull Request #2011: Single-file CI and code style adoption

14612 of 26123 relevant lines covered (55.94%)

462107.16 hits per line

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

65.26
/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) {
187✔
30
    the_pip = this ;
187✔
31
    return ;
187✔
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() {
198✔
47
    //std::cout << "top level names at initialization" << std::endl ;
48
    Trick::ALLOC_INFO_MAP_ITER aim_it ;
198✔
49
    for ( aim_it = trick_MM->alloc_info_map_begin() ; aim_it != trick_MM->alloc_info_map_end() ; ++aim_it ) {
5,554✔
50
        ALLOC_INFO * alloc_info = (*aim_it).second ;
5,356✔
51
        if ( alloc_info->name != NULL and alloc_info->user_type_name != NULL ) {
5,356✔
52
            std::stringstream ss ;
5,105✔
53
            std::string user_type_name = alloc_info->user_type_name ;
5,105✔
54
            size_t start_colon ;
55
            while ( ( start_colon = user_type_name.find("::") ) != std::string::npos ) {
5,713✔
56
                user_type_name.replace( start_colon , 2 , "__" ) ;
608✔
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 ;
5,105✔
63
            ss << "    if '" << alloc_info->name << "' not in globals() or " ;
5,105✔
64
            ss << alloc_info->name << ".thisown == False:" <<  std::endl ;
5,105✔
65
            ss << "        " << alloc_info->name << " = " ;
5,105✔
66
            ss << "trick.castAs" << user_type_name << "(int(" << alloc_info->start << "))" << std::endl ;
5,105✔
67
            ss << "except AttributeError:" << std::endl ;
5,105✔
68
            ss << "    pass" << std::endl ;
5,105✔
69
            PyGILState_STATE gstate = PyGILState_Ensure();
5,105✔
70
            PyRun_SimpleString(ss.str().c_str()) ;
5,105✔
71
            PyGILState_Release(gstate);
5,105✔
72
        }
5,105✔
73
    }
74
}
198✔
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() {
187✔
88
    /** @par Detailed Design: */
89

90
    FILE *input_fp ;
91
    int ret ;
92
    std::string error_message ;
187✔
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() ;
187✔
101

102
    // Run Py_Initialze after init_swig_modules for python 3.x
103
#if PY_VERSION_HEX >= 0x03000000
104
    Py_Initialize();
187✔
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(
187✔
110
     "import sys\n"
111
     "import os\n"
112
     "import struct\n"
113
     "import binascii\n"
114
     "if 'VIRTUAL_ENV' in os.environ:\n"
115
     "    sys.path.append(os.path.join(os.environ['VIRTUAL_ENV'], \"lib\", f\"python{sys.version_info.major}.{sys.version_info.minor}\", \"site-packages\"))\n"
116
     "sys.path.append(os.getcwd() + '/trick.zip')\n"
117
     "sys.path.append(os.path.join(os.environ['TRICK_HOME'], 'share/trick/pymods'))\n"
118
     "sys.path += map(str.strip, os.environ['TRICK_PYTHON_PATH'].split(':'))\n"
119
     "import trick\n"
120
     "sys.path.append(os.getcwd() + \"/Modified_data\")\n"
121
    ) ;
122

123
    /* Make shortcut names for all known sim_objects. */
124
    get_TMM_named_variables() ;
187✔
125

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

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

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

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

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

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

160
    if ( save_input ) {
185✔
161
        PyRun_SimpleString("trick.close_input_file_log()") ;
×
162
        PyRun_SimpleString("sys.settrace(None)") ;
×
163
    }
164

165
    fclose(input_fp) ;
185✔
166

167
    // Release the GIL from the main thread.
168
    Py_UNBLOCK_THREADS
185✔
169

170
    return(0) ;
185✔
171
}
187✔
172

173
//Command to parse the given string.
174
int Trick::IPPython::parse(std::string in_string) {
157✔
175

176
    int ret ;
177
    in_string += "\n" ;
157✔
178
    PyGILState_STATE gstate = PyGILState_Ensure();
157✔
179
    ret = PyRun_SimpleString(in_string.c_str()) ;
157✔
180
    PyGILState_Release(gstate);
157✔
181

182
    return ret ;
157✔
183

184
}
185

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

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

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

208
    return py_ret ;
46✔
209

210
}
211

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

219
int Trick::IPPython::shutdown() {
154✔
220

221
    if ( Py_IsInitialized() ) {
154✔
222
        // Obtain the GIL so that we can shut down properly
223
        Py_BLOCK_THREADS
154✔
224
        Py_Finalize();
154✔
225
    }
226
    return(0) ;
154✔
227
}
228

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

235
void revive_the_units_conversion_messenger() {
×
236
    message_publish(MSG_WARNING, "revive_the_units_conversion_messenger() is deprecated\n") ;
×
237
    the_pip->shoot_the_units_conversion_messenger(false) ;
×
238
}
×
239

240
int check_units_conversion_messenger_for_signs_of_life() {
×
241
    message_publish(MSG_WARNING, "check_units_conversion_messenger_for_signs_of_life() is deprecated\n") ;
×
242
    return the_pip->get_units_conversion_msgs() ;
×
243
}
244
//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