diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index d8ce9a7cd06..eabed37bceb 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -206,7 +206,7 @@ jobs: timeout-minutes: 75 strategy: matrix: - python-version: [ "3.11", "3.12" ] + python-version: [ "3.11", "3.12", "3.13" ] steps: - name: Checkout code uses: actions/checkout@v4 diff --git a/docs/source/Install/installOnLinux.rst b/docs/source/Install/installOnLinux.rst index 3b932650d49..037d11a084b 100644 --- a/docs/source/Install/installOnLinux.rst +++ b/docs/source/Install/installOnLinux.rst @@ -12,7 +12,7 @@ Software setup In order to run Basilisk, the following software will be necessary. This document outline how to install this support software. -- `Python `__ 3.8 to 3.12 +- `Python `__ 3.8 to 3.13 - `SWIG `__ (version 4.x) - `GCC `__ - (Optional) Get the `GitKraken `__ diff --git a/docs/source/Install/installOnMacOS.rst b/docs/source/Install/installOnMacOS.rst index 7b628b42100..e91b893f88e 100644 --- a/docs/source/Install/installOnMacOS.rst +++ b/docs/source/Install/installOnMacOS.rst @@ -8,7 +8,7 @@ Setup On macOS ============== These instruction outline how to install Basilisk (BSK) on a clean version of macOS. -Basilisk requires the use of Python 3.8 to 3.12. +Basilisk requires the use of Python 3.8 to 3.13. The following python package dependencies are automatically checked and installed in the steps below. diff --git a/docs/source/Install/installOnWindows.rst b/docs/source/Install/installOnWindows.rst index e9aeae9863f..a2b6f267b96 100644 --- a/docs/source/Install/installOnWindows.rst +++ b/docs/source/Install/installOnWindows.rst @@ -13,7 +13,7 @@ Software setup In order to run Basilisk, the following software will be necessary: -- `Python `__ 3.8 to 3.12 +- `Python `__ 3.8 to 3.13 - `pip `__ - Visual Studios 15 2017 or greater - `Swig `__ version 4.X diff --git a/docs/source/Support/bskReleaseNotes.rst b/docs/source/Support/bskReleaseNotes.rst index c3b8a30637a..04cf5b18211 100644 --- a/docs/source/Support/bskReleaseNotes.rst +++ b/docs/source/Support/bskReleaseNotes.rst @@ -51,6 +51,9 @@ Version |release| and conversions. - Updated install requirements to not manually install ``cmake``, but have it installed with pip by including it in ``requirements_dev.txt``. A ``conan`` dependency requires Basilisk to use ``cmake<4.0`` for now. +- Add support for python 3.13 by removing the use of ``eval()`` and most ``exec()`` methods, + rewrote ``methodizeEvent()`` in ``SimulationBaseClass.py``. If you use python 3.13+ the + scope of the ``eval()`` method has changed (see https://peps.python.org/pep-0667/). Version 2.6.0 (Feb. 21, 2025) diff --git a/examples/MonteCarloExamples/scenarioRerunMonteCarlo.py b/examples/MonteCarloExamples/scenarioRerunMonteCarlo.py index 4ee72ba65be..8ee014bf94a 100644 --- a/examples/MonteCarloExamples/scenarioRerunMonteCarlo.py +++ b/examples/MonteCarloExamples/scenarioRerunMonteCarlo.py @@ -25,10 +25,10 @@ """ - import inspect import os import sys +import importlib from Basilisk.utilities.MonteCarlo.Controller import Controller from Basilisk.utilities.MonteCarlo.RetentionPolicy import RetentionPolicy @@ -53,7 +53,6 @@ def run(time=None): 3) Provide the run numbers you wish to rerun 4) Add any new retention policies to the bottom - """ # Step 1-3: Change to the relevant scenario @@ -68,12 +67,15 @@ def run(time=None): icName = path + "/" + mcName # Use MC script name for directory newDataDir = path + "/" + mcName + "/rerun" - # Import the base scenario module, not the MC script - exec('import '+ scenarioName) - simulationModule = eval(scenarioName + ".scenario_AttFeedback") # Use the actual scenario function + # Use importlib to import the scenario module + scenarioModule = importlib.import_module(scenarioName) + + # Access the class and methods dynamically using getattr() + simulationModule = getattr(scenarioModule, scenarioName) + if time is not None: - exec (scenarioName + '.scenario_AttFeedback.simBaseTime = time') - executionModule = eval(scenarioName + ".runScenario") + simulationModule.simBaseTime = time + executionModule = getattr(scenarioModule, "runScenario") monteCarlo.setSimulationFunction(simulationModule) monteCarlo.setExecutionFunction(executionModule) @@ -84,18 +86,15 @@ def run(time=None): monteCarlo.setShouldDisperseSeeds(False) monteCarlo.shouldArchiveParameters = False - # Step 4: Add any additional retention policies desired retentionPolicy = RetentionPolicy() retentionPolicy.logRate = int(2E9) retentionPolicy.addMessageLog("attGuidMsg", ["sigma_BR"]) monteCarlo.addRetentionPolicy(retentionPolicy) - failed = monteCarlo.runInitialConditions(runsList) assert len(failed) == 0, "Should run ICs successfully" - if __name__ == "__main__": run() diff --git a/pyproject.toml b/pyproject.toml index 1d1a17763f2..92afcda186c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,7 @@ requires = [ [project] name = 'Basilisk' dynamic = ["version", "dependencies"] -requires-python = ">=3.8, <3.13" +requires-python = ">=3.8, <3.14" readme = "README.md" license = {file = "LICENSE"} diff --git a/src/architecture/_GeneralModuleFiles/swig_conly_data.i b/src/architecture/_GeneralModuleFiles/swig_conly_data.i index 6c34d31f09e..f964ebc7298 100644 --- a/src/architecture/_GeneralModuleFiles/swig_conly_data.i +++ b/src/architecture/_GeneralModuleFiles/swig_conly_data.i @@ -250,7 +250,12 @@ ARRAY2ASLIST(bool, PyBool_FromLong, PyObject_IsTrue) def getStructSize(self): try: - return eval('sizeof_' + repr(self).split(';')[0].split('.')[-1]) + class_name = repr(self).split(';')[0].split('.')[-1] + sizeof_variable_name = 'sizeof_' + class_name + size = globals().get(sizeof_variable_name) + + if size is None: + raise ValueError(f"{sizeof_variable_name} not found in globals()") except (NameError) as e: typeString = 'sizeof_' + repr(self).split(';')[0].split('.')[-1] raise NameError(e.message + '\nYou tried to get this size macro: ' + typeString + diff --git a/src/fswAlgorithms/attControl/mtbMomentumManagementSimple/mtbMomentumManagementSimple.c b/src/fswAlgorithms/attControl/mtbMomentumManagementSimple/mtbMomentumManagementSimple.c index 533219b8f74..707c571c04e 100644 --- a/src/fswAlgorithms/attControl/mtbMomentumManagementSimple/mtbMomentumManagementSimple.c +++ b/src/fswAlgorithms/attControl/mtbMomentumManagementSimple/mtbMomentumManagementSimple.c @@ -99,7 +99,7 @@ void Update_mtbMomentumManagementSimple(mtbMomentumManagementSimpleConfig *confi * Read the input message and initialize output message. */ RWSpeedMsgPayload rwSpeedsInMsgBuffer = RWSpeedMsg_C_read(&configData->rwSpeedsInMsg); - CmdTorqueBodyMsgPayload tauMtbRequestOutMsgBuffer = CmdTorqueBodyMsg_C_zeroMsgPayload(&configData->tauMtbRequestOutMsg); + CmdTorqueBodyMsgPayload tauMtbRequestOutMsgBuffer = CmdTorqueBodyMsg_C_zeroMsgPayload(); /*! - Compute wheel momentum in Body frame components by calculating it first in the wheel frame and then transforming it from the wheel space into the body frame using Gs.*/ diff --git a/src/fswAlgorithms/attDetermination/sunlineUKF/_UnitTest/test_SunLineUKF.py b/src/fswAlgorithms/attDetermination/sunlineUKF/_UnitTest/test_SunLineUKF.py index 453bdc49112..9afd6b03a71 100644 --- a/src/fswAlgorithms/attDetermination/sunlineUKF/_UnitTest/test_SunLineUKF.py +++ b/src/fswAlgorithms/attDetermination/sunlineUKF/_UnitTest/test_SunLineUKF.py @@ -61,7 +61,13 @@ def setupFilterData(filterObject): ]) def test_all_sunline_kf(show_plots, function): """Module Unit Test""" - [testResults, testMessage] = eval(function + '(show_plots)') + testFunction = globals().get(function) + + if testFunction is None: + raise ValueError(f"Function '{function}' not found in global scope") + + [testResults, testMessage] = testFunction(show_plots) + assert testResults < 1, testMessage diff --git a/src/fswAlgorithms/attGuidance/eulerRotation/_UnitTest/test_eulerRotation.py b/src/fswAlgorithms/attGuidance/eulerRotation/_UnitTest/test_eulerRotation.py index 8e3682e84eb..c1221354963 100644 --- a/src/fswAlgorithms/attGuidance/eulerRotation/_UnitTest/test_eulerRotation.py +++ b/src/fswAlgorithms/attGuidance/eulerRotation/_UnitTest/test_eulerRotation.py @@ -43,7 +43,12 @@ ]) def test_all_test_eulerRotation(show_plots, function): """Module Unit Test""" - [testResults, testMessage] = eval(function + '(show_plots)') + testFunction = globals().get(function) + + if testFunction is None: + raise ValueError(f"Function '{function}' not found in global scope") + + [testResults, testMessage] = testFunction(show_plots) assert testResults < 1, testMessage diff --git a/src/fswAlgorithms/attGuidance/inertial3DSpin/_UnitTest/test_inertial3DSpin.py b/src/fswAlgorithms/attGuidance/inertial3DSpin/_UnitTest/test_inertial3DSpin.py index 24a2bb1e0e8..ed2a609e220 100755 --- a/src/fswAlgorithms/attGuidance/inertial3DSpin/_UnitTest/test_inertial3DSpin.py +++ b/src/fswAlgorithms/attGuidance/inertial3DSpin/_UnitTest/test_inertial3DSpin.py @@ -44,7 +44,12 @@ ]) def test_stateArchitectureAllTests(show_plots, function): """Module Unit Test""" - [testResults, testMessage] = eval(function + '(show_plots)') + testFunction = globals().get(function) + + if testFunction is None: + raise ValueError(f"Function '{function}' not found in global scope") + + [testResults, testMessage] = testFunction(show_plots) assert testResults < 1, testMessage @@ -321,4 +326,4 @@ def subModuleTestFunction2(show_plots): # if __name__ == "__main__": # all_inertial3DSpin(False) - subModuleTestFunction2(False) \ No newline at end of file + subModuleTestFunction2(False) diff --git a/src/fswAlgorithms/effectorInterfaces/dipoleMapping/dipoleMapping.c b/src/fswAlgorithms/effectorInterfaces/dipoleMapping/dipoleMapping.c index 48fda07b433..21932e69c0c 100644 --- a/src/fswAlgorithms/effectorInterfaces/dipoleMapping/dipoleMapping.c +++ b/src/fswAlgorithms/effectorInterfaces/dipoleMapping/dipoleMapping.c @@ -80,7 +80,7 @@ void Update_dipoleMapping(dipoleMappingConfig *configData, uint64_t callTime, in * Read the input messages and initialize output message. */ DipoleRequestBodyMsgPayload dipoleRequestBodyInMsgBuffer = DipoleRequestBodyMsg_C_read(&configData->dipoleRequestBodyInMsg); - MTBCmdMsgPayload dipoleRequestMtbOutMsgBuffer = MTBCmdMsg_C_zeroMsgPayload(&configData->dipoleRequestMtbOutMsg); + MTBCmdMsgPayload dipoleRequestMtbOutMsgBuffer = MTBCmdMsg_C_zeroMsgPayload(); /*! - Map the requested Body frame dipole request to individual torque rod dipoles.*/ mMultV(configData->steeringMatrix, configData->mtbArrayConfigParams.numMTB, 3, dipoleRequestBodyInMsgBuffer.dipole_B, dipoleRequestMtbOutMsgBuffer.mtbDipoleCmds); diff --git a/src/fswAlgorithms/transDetermination/chebyPosEphem/_UnitTest/test_chebyPosEphem.py b/src/fswAlgorithms/transDetermination/chebyPosEphem/_UnitTest/test_chebyPosEphem.py index 2be47b6a972..999cd4bb1f5 100644 --- a/src/fswAlgorithms/transDetermination/chebyPosEphem/_UnitTest/test_chebyPosEphem.py +++ b/src/fswAlgorithms/transDetermination/chebyPosEphem/_UnitTest/test_chebyPosEphem.py @@ -49,7 +49,12 @@ ]) def test_chebyPosFitAllTest(show_plots, function): """Module Unit Test""" - [testResults, testMessage] = eval(function + '(show_plots)') + testFunction = globals().get(function) + + if testFunction is None: + raise ValueError(f"Function '{function}' not found in global scope") + + [testResults, testMessage] = testFunction(show_plots) assert testResults < 1, testMessage diff --git a/src/simulation/dynamics/HingedRigidBodies/_UnitTest/test_hingedRigidBodyStateEffector.py b/src/simulation/dynamics/HingedRigidBodies/_UnitTest/test_hingedRigidBodyStateEffector.py index d5b6debc818..0e5afbf8000 100644 --- a/src/simulation/dynamics/HingedRigidBodies/_UnitTest/test_hingedRigidBodyStateEffector.py +++ b/src/simulation/dynamics/HingedRigidBodies/_UnitTest/test_hingedRigidBodyStateEffector.py @@ -54,7 +54,12 @@ ]) def test_hingedRigidBody(show_plots, function): """Module Unit Test""" - [testResults, testMessage] = eval(function + '(show_plots)') + testFunction = globals().get(function) + + if testFunction is None: + raise ValueError(f"Function '{function}' not found in global scope") + + [testResults, testMessage] = testFunction(show_plots) assert testResults < 1, testMessage @pytest.mark.parametrize("useScPlus", [True, False]) @@ -296,18 +301,18 @@ def hingedRigidBodyNoGravity(show_plots): # --fulltrace command line option is specified. __tracebackhide__ = True - testFailCount = 0 # zero unit test result counter + testFailCount = 0 # zero unit test result counter testMessages = [] # create empty list to store test log messages - + scObject = spacecraftSystem.SpacecraftSystem() scObject.ModelTag = "spacecraftBody" - + unitTaskName = "unitTask" # arbitrary name (don't change) unitProcessName = "TestProcess" # arbitrary name (don't change) - + # Create a sim module as an empty container unitTestSim = SimulationBaseClass.SimBaseClass() - + # Create test thread testProcessRate = macros.sec2nano(0.001) # update process rate update time testProc = unitTestSim.CreateNewProcess(unitProcessName) @@ -360,7 +365,7 @@ def hingedRigidBodyNoGravity(show_plots): dataLog = scObject.primaryCentralSpacecraft.scStateOutMsg.recorder() unitTestSim.AddModelToTask(unitTaskName, dataLog) - + scLog = pythonVariableLogger.PythonVariableLogger({ "totOrbEnergy": lambda _: scObject.primaryCentralSpacecraft.totOrbEnergy, "totOrbAngMomPntN_N": lambda _: scObject.primaryCentralSpacecraft.totOrbAngMomPntN_N, @@ -878,7 +883,7 @@ def hingedRigidBodyThetaSS(show_plots): PlotTitle = "BOE Calculation for Steady State Theta 2 Deflection vs Simulation" format = r"width=0.8\textwidth" unitTestSupport.writeFigureLaTeX(PlotName, PlotTitle, plt, format, path) - + if show_plots: plt.show() plt.close("all") @@ -1878,4 +1883,4 @@ class boxAndWingParameters: # test_hingedRigidBodyThetaSS(True) # test_hingedRigidBodyFrequencyAmp(True) # test_hingedRigidBodyMotorTorque(True, True) - hingedRigidBodyLagrangVsBasilisk(True) \ No newline at end of file + hingedRigidBodyLagrangVsBasilisk(True) diff --git a/src/simulation/dynamics/Integrators/_UnitTest/test_Integrators.py b/src/simulation/dynamics/Integrators/_UnitTest/test_Integrators.py index ce3aba0715d..4fe91d05206 100755 --- a/src/simulation/dynamics/Integrators/_UnitTest/test_Integrators.py +++ b/src/simulation/dynamics/Integrators/_UnitTest/test_Integrators.py @@ -204,8 +204,7 @@ def run(doUnitTests, show_plots, integratorCase): # np.set_printoptions(precision=16) fileNameString = filename[len(path) + 6:-3] - if integratorCase == "bogackiShampine": - plt.close("all") # clears out plots from earlier test runs + plt.close("all") # clears out plots from earlier test runs # draw orbit in perifocal frame b = oe.a * np.sqrt(1 - oe.e * oe.e) diff --git a/src/simulation/dynamics/constraintEffector/_UnitTest/test_ConstraintDynamicEffectorUnit.py b/src/simulation/dynamics/constraintEffector/_UnitTest/test_ConstraintDynamicEffectorUnit.py index b4cf9639e63..075b7405895 100644 --- a/src/simulation/dynamics/constraintEffector/_UnitTest/test_ConstraintDynamicEffectorUnit.py +++ b/src/simulation/dynamics/constraintEffector/_UnitTest/test_ConstraintDynamicEffectorUnit.py @@ -69,7 +69,13 @@ def test_constraintEffector(show_plots, function): """ - eval(function + '(show_plots)') + testFunction = globals().get(function) + + if testFunction is None: + raise ValueError(f"Function '{function}' not found in global scope") + + result = testFunction(show_plots) + def constraintEffectorOrbitalConservation(show_plots): diff --git a/src/simulation/dynamics/extForceTorque/_UnitTest/test_extForceTorqueIntegrated.py b/src/simulation/dynamics/extForceTorque/_UnitTest/test_extForceTorqueIntegrated.py index 13e0e8d0de8..1ad2a25e752 100644 --- a/src/simulation/dynamics/extForceTorque/_UnitTest/test_extForceTorqueIntegrated.py +++ b/src/simulation/dynamics/extForceTorque/_UnitTest/test_extForceTorqueIntegrated.py @@ -36,7 +36,13 @@ ]) def test_ForceBodyAndTorqueAllTest(show_plots, function): """Module Unit Test""" - [testResults, testMessage] = eval(function + '()') + testFunction = globals().get(function) + + if testFunction is None: + raise ValueError(f"Function '{function}' not found in global scope") + + [testResults, testMessage] = testFunction() + assert testResults < 1, testMessage diff --git a/src/simulation/dynamics/gravityEffector/_UnitTest/test_gravitySpacecraft.py b/src/simulation/dynamics/gravityEffector/_UnitTest/test_gravitySpacecraft.py index a3935fa99be..9f43b12f0cc 100644 --- a/src/simulation/dynamics/gravityEffector/_UnitTest/test_gravitySpacecraft.py +++ b/src/simulation/dynamics/gravityEffector/_UnitTest/test_gravitySpacecraft.py @@ -50,7 +50,12 @@ ]) def test_gravityEffectorAllTest(show_plots, function): """Module Unit Test""" - [testResults, testMessage] = eval(function + '(show_plots)') + testFunction = globals().get(function) + + if testFunction is None: + raise ValueError(f"Function '{function}' not found in global scope") + + [testResults, testMessage] = testFunction(show_plots) assert testResults < 1, testMessage diff --git a/src/simulation/dynamics/linearTranslationalBodies/linearTranslationBodiesNDOF/_UnitTest/test_linearTranslationNDOFStateEffector.py b/src/simulation/dynamics/linearTranslationalBodies/linearTranslationBodiesNDOF/_UnitTest/test_linearTranslationNDOFStateEffector.py index 62a26db77f5..da5bb9a308d 100644 --- a/src/simulation/dynamics/linearTranslationalBodies/linearTranslationBodiesNDOF/_UnitTest/test_linearTranslationNDOFStateEffector.py +++ b/src/simulation/dynamics/linearTranslationalBodies/linearTranslationBodiesNDOF/_UnitTest/test_linearTranslationNDOFStateEffector.py @@ -71,8 +71,12 @@ def test_translatingBody(show_plots, function): against their initial values. """ - eval(function + '(show_plots)') + testFunction = globals().get(function) + if testFunction is None: + raise ValueError(f"Function '{function}' not found in global scope") + + testFunction(show_plots) def translatingBodyNoInput(show_plots): r""" diff --git a/src/simulation/dynamics/linearTranslationalBodies/linearTranslationBodiesOneDOF/_UnitTest/test_linearTranslationOneDOFStateEffector.py b/src/simulation/dynamics/linearTranslationalBodies/linearTranslationBodiesOneDOF/_UnitTest/test_linearTranslationOneDOFStateEffector.py index 78eff1e2d4c..08b792e6bd0 100644 --- a/src/simulation/dynamics/linearTranslationalBodies/linearTranslationBodiesOneDOF/_UnitTest/test_linearTranslationOneDOFStateEffector.py +++ b/src/simulation/dynamics/linearTranslationalBodies/linearTranslationBodiesOneDOF/_UnitTest/test_linearTranslationOneDOFStateEffector.py @@ -71,12 +71,18 @@ def test_translatingBody(show_plots, function): should be constant when tested against their initial values. """ + + func = globals().get(function) + + if func is None: + raise ValueError(f"Function '{function}' not found in global scope") + if function == "translatingBodyCommandedForce": - eval(function + '(show_plots, 1.0)') + func(show_plots, 1.0) elif function == "translatingBodyRhoReference": - eval(function + '(show_plots, 0.5)') + func(show_plots, 0.5) else: - eval(function + '(show_plots)') + func(show_plots) # rho ref and cmd force are zero, no lock flag diff --git a/src/simulation/dynamics/spacecraft/_UnitTest/test_spacecraft.py b/src/simulation/dynamics/spacecraft/_UnitTest/test_spacecraft.py index 11e97169eaa..fa9285761db 100644 --- a/src/simulation/dynamics/spacecraft/_UnitTest/test_spacecraft.py +++ b/src/simulation/dynamics/spacecraft/_UnitTest/test_spacecraft.py @@ -59,12 +59,18 @@ def addTimeColumn(time, data): ]) def test_spacecraftAllTest(show_plots, function): """Module Unit Test""" + func = globals().get(function) + + if func is None: + raise ValueError(f"Function '{function}' not found in global scope") + if function == "scOptionalRef": - [testResults, testMessage] = eval(function + '(show_plots, 1e-3)') - elif function == "scAccumDV" or function == "scAccumDVExtForce": - [testResults, testMessage] = eval(function + '()') + [testResults, testMessage] = func(show_plots, 1e-3) + elif function in ["scAccumDV", "scAccumDVExtForce"]: + [testResults, testMessage] = func() else: - [testResults, testMessage] = eval(function + '(show_plots)') + [testResults, testMessage] = func(show_plots) + assert testResults < 1, testMessage diff --git a/src/simulation/dynamics/spacecraftSystem/_UnitTest/test_multiSpacecraft.py b/src/simulation/dynamics/spacecraftSystem/_UnitTest/test_multiSpacecraft.py index d703038a79c..1cee31ca923 100644 --- a/src/simulation/dynamics/spacecraftSystem/_UnitTest/test_multiSpacecraft.py +++ b/src/simulation/dynamics/spacecraftSystem/_UnitTest/test_multiSpacecraft.py @@ -50,7 +50,13 @@ def addTimeColumn(time, data): ]) def test_spacecraftSystemAllTest(show_plots, function): """Module Unit Test""" - [testResults, testMessage] = eval(function + '(show_plots)') + func = globals().get(function) + + if func is None: + raise ValueError(f"Function '{function}' not found in global scope") + + [testResults, testMessage] = func(show_plots) + assert testResults < 1, testMessage @@ -748,4 +754,4 @@ def SCConnectedAndUnconnected(show_plots): if __name__ == "__main__": # SCConnected(True) - SCConnectedAndUnconnected(True) \ No newline at end of file + SCConnectedAndUnconnected(True) diff --git a/src/simulation/dynamics/spinningBodies/spinningBodiesNDOF/_UnitTest/test_spinningBodyNDOFStateEffector.py b/src/simulation/dynamics/spinningBodies/spinningBodiesNDOF/_UnitTest/test_spinningBodyNDOFStateEffector.py index 7c2efc13a2f..bd074f34370 100644 --- a/src/simulation/dynamics/spinningBodies/spinningBodiesNDOF/_UnitTest/test_spinningBodyNDOFStateEffector.py +++ b/src/simulation/dynamics/spinningBodies/spinningBodiesNDOF/_UnitTest/test_spinningBodyNDOFStateEffector.py @@ -67,7 +67,12 @@ def test_spinningBody(show_plots, function): against their initial values. """ - eval(function + '(show_plots)') + func = globals().get(function) + + if func is None: + raise ValueError(f"Function '{function}' not found in global scope") + + func(show_plots) def spinningBodyNoInput(show_plots): diff --git a/src/simulation/onboardDataHandling/instrument/simpleInstrument/_UnitTest/test_simpleInstrument.py b/src/simulation/onboardDataHandling/instrument/simpleInstrument/_UnitTest/test_simpleInstrument.py index 38cd54b90d7..4ee7880b265 100644 --- a/src/simulation/onboardDataHandling/instrument/simpleInstrument/_UnitTest/test_simpleInstrument.py +++ b/src/simulation/onboardDataHandling/instrument/simpleInstrument/_UnitTest/test_simpleInstrument.py @@ -40,7 +40,13 @@ ]) def test_simpleInstrumentAll(show_plots, function): """Module Unit Test""" - [testResults, testMessage] = eval(function + '()') + func = globals().get(function) + + if func is None: + raise ValueError(f"Function '{function}' not found in global scope") + + [testResults, testMessage] = func() + assert testResults < 1, testMessage @@ -172,4 +178,4 @@ def checkStatus(): # if __name__ == "__main__": # checkDefault() - checkStatus() \ No newline at end of file + checkStatus() diff --git a/src/simulation/onboardDataHandling/transmitter/_UnitTest/test_simpleTransmitter.py b/src/simulation/onboardDataHandling/transmitter/_UnitTest/test_simpleTransmitter.py index 543c8bc7cfe..8edeb57141b 100644 --- a/src/simulation/onboardDataHandling/transmitter/_UnitTest/test_simpleTransmitter.py +++ b/src/simulation/onboardDataHandling/transmitter/_UnitTest/test_simpleTransmitter.py @@ -40,7 +40,13 @@ ]) def test_simpleTransmitterAll(show_plots, function): """Module Unit Test""" - [testResults, testMessage] = eval(function + '()') + func = globals().get(function) + + if func is None: + raise ValueError(f"Function '{function}' not found in global scope") + + [testResults, testMessage] = func() + assert testResults < 1, testMessage @@ -209,4 +215,4 @@ def checkStatus(): # if __name__ == "__main__": checkDefault() - checkStatus() \ No newline at end of file + checkStatus() diff --git a/src/simulation/power/simplePowerSink/_UnitTest/test_unitSimplePowerSink.py b/src/simulation/power/simplePowerSink/_UnitTest/test_unitSimplePowerSink.py index 1fe62748393..1d36003fc2f 100644 --- a/src/simulation/power/simplePowerSink/_UnitTest/test_unitSimplePowerSink.py +++ b/src/simulation/power/simplePowerSink/_UnitTest/test_unitSimplePowerSink.py @@ -47,7 +47,13 @@ ]) def test_allTest_SimplePowerSink(show_plots, function): """Module Unit Test""" - [testResults, testMessage] = eval(function + '()') + func = globals().get(function) + + if func is None: + raise ValueError(f"Function '{function}' not found in global scope") + + [testResults, testMessage] = func() + assert testResults < 1, testMessage diff --git a/src/tests/test_messaging.py b/src/tests/test_messaging.py index 1e83935e005..a39b7cce816 100644 --- a/src/tests/test_messaging.py +++ b/src/tests/test_messaging.py @@ -20,7 +20,7 @@ # # Integrated tests # -# Purpose: This script runs a series of test to ensure that the messaging +# Purpose: This script runs a series of test to ensure that the messaging # interface is properly set up for C and Cpp messages # Author: Benjamin Bercovici # Creation Date: June 4th, 2021 @@ -56,17 +56,17 @@ def test_cpp_msg_subscription_check(): bskLogging.setDefaultLogLevel(bskLogging.BSK_WARNING) testFailCount = 0 # zero unit test result counter testMessages = [] # create empty array to store test log messages - + # Try out all the existing cpp messages - cppMessages = [ el for el in dir(messaging) if el.endswith("Msg")] - + cppMessages = [ el for el in dir(messaging) if el.endswith("Msg")] + for el in cppMessages: - + # Create three messages - msgA = eval("messaging." + el + "()") - msgB = eval("messaging." + el + "()") - msgC = eval("messaging." + el + "()") + msgA = getattr(messaging, el)() + msgB = getattr(messaging, el)() + msgC = getattr(messaging, el)() # Create subscribers to pair messages msgB_subscriber = msgB.addSubscriber() @@ -86,8 +86,8 @@ def test_cpp_msg_subscription_check(): if msgC_subscriber.isSubscribedTo(msgA) != 0: testFailCount += 1 testMessages.append(el + ": msgC_subscriber.isSubscribedTo(msgA) should be False") - - + + # Change subscription pattern msgB_subscriber.subscribeTo(msgC) # Subscribe B to C msgC_subscriber.subscribeTo(msgA) # Subscribe C to A @@ -103,8 +103,8 @@ def test_cpp_msg_subscription_check(): testFailCount += 1 testMessages.append(el + ": msgC_subscriber.isSubscribedTo(msgB) should be False") - - + + if testFailCount == 0: print("PASSED") else: @@ -122,18 +122,18 @@ def test_c_msg_subscription_check(): bskLogging.setDefaultLogLevel(bskLogging.BSK_WARNING) testFailCount = 0 # zero unit test result counter testMessages = [] # create empty array to store test log messages - + # Try out all the existing c messages - cMessages = [ el for el in dir(messaging) if el.endswith("Msg_C")] + cMessages = [ el for el in dir(messaging) if el.endswith("Msg_C")] + - for el in cMessages: - + # Create three messages - msgA = eval("messaging." + el + "()") - msgB = eval("messaging." + el + "()") - msgC = eval("messaging." + el + "()") + msgA = getattr(messaging, el)() + msgB = getattr(messaging, el)() + msgC = getattr(messaging, el)() # Subscribe msgB.subscribeTo(msgA) # Subscribe B to A @@ -149,8 +149,8 @@ def test_c_msg_subscription_check(): if msgC.isSubscribedTo(msgA) != 0: testFailCount += 1 testMessages.append(el + ": msgC.isSubscribedTo(msgA) should be False") - - + + # Change subscription pattern msgB.subscribeTo(msgC) # Subscribe B to C msgC.subscribeTo(msgA) # Subscribe C to A @@ -166,8 +166,8 @@ def test_c_msg_subscription_check(): testFailCount += 1 testMessages.append(el + ": msgC.isSubscribedTo(msgB) should be False") - - + + if testFailCount == 0: print("PASSED") else: @@ -176,34 +176,34 @@ def test_c_msg_subscription_check(): def test_c_2_cpp_msg_subscription_check(): - + bskLogging.setDefaultLogLevel(bskLogging.BSK_WARNING) testFailCount = 0 # zero unit test result counter testMessages = [] # create empty array to store test log messages - + # Try out all the existing messages - cppMessages = [ el for el in dir(messaging) if el.endswith("Msg")] - cMessages = [ el for el in dir(messaging) if el.endswith("Msg_C")] - + cppMessages = [ el for el in dir(messaging) if el.endswith("Msg")] + cMessages = [ el for el in dir(messaging) if el.endswith("Msg_C")] + # Find common messages common_messages = [el for el in cppMessages if el + "_C" in cMessages] for el in common_messages: - + # Create c and cpp messages - msgA = eval("messaging." + el + "()") - msgB = eval("messaging." + el + "()") + msgA = getattr(messaging, el)() + msgB = getattr(messaging, el)() + + msgC = getattr(messaging, el + "_C")() + msgD = getattr(messaging, el + "_C")() - msgC = eval("messaging." + el + "_C()") - msgD = eval("messaging." + el + "_C()") - # Subscribe msgC.subscribeTo(msgA) # Subscribe C to A msgD.subscribeTo(msgB) # Subscribe D to B - + # Check if msgC.isSubscribedTo(msgA) != 1: testFailCount += 1 @@ -217,7 +217,7 @@ def test_c_2_cpp_msg_subscription_check(): if msgC.isSubscribedTo(msgB) != 0: testFailCount += 1 testMessages.append(el + ": msgC.isSubscribedTo(msgB) should be False") - + # Change subscription pattern msgC.subscribeTo(msgB) # Subscribe C to B msgD.subscribeTo(msgA) # Subscribe D to A @@ -236,8 +236,8 @@ def test_c_2_cpp_msg_subscription_check(): testFailCount += 1 testMessages.append(el + ": msgD.isSubscribedTo(msgB) should be False") - - + + if testFailCount == 0: print("PASSED") else: @@ -249,29 +249,29 @@ def test_cpp_2_c_msg_subscription_check(): bskLogging.setDefaultLogLevel(bskLogging.BSK_WARNING) testFailCount = 0 # zero unit test result counter testMessages = [] # create empty array to store test log messages - + # Try out all the existing messages - cppMessages = [ el for el in dir(messaging) if el.endswith("Msg")] - cMessages = [ el for el in dir(messaging) if el.endswith("Msg_C")] - + cppMessages = [ el for el in dir(messaging) if el.endswith("Msg")] + cMessages = [ el for el in dir(messaging) if el.endswith("Msg_C")] + # Find common messages common_messages = [el for el in cppMessages if el + "_C" in cMessages] for el in common_messages: - + # Create c and cpp messages - msgA = eval("messaging." + el + "_C()") - msgB = eval("messaging." + el + "_C()") + msgA = getattr(messaging, el + "_C")() + msgB = getattr(messaging, el + "_C")() - msgC = eval("messaging." + el + "()") - msgD = eval("messaging." + el + "()") + msgC = getattr(messaging, el)() + msgD = getattr(messaging, el)() # Create subscribers to pair messages msgC_subscriber = msgC.addSubscriber() msgD_subscriber = msgD.addSubscriber() - + # Subscribe msgC_subscriber.subscribeTo(msgA) # Subscribe C to A msgD_subscriber.subscribeTo(msgB) # Subscribe D to B @@ -289,7 +289,7 @@ def test_cpp_2_c_msg_subscription_check(): if msgC_subscriber.isSubscribedTo(msgB) != 0: testFailCount += 1 testMessages.append(el + ": msgC_subscriber.isSubscribedTo(msgB) should be False") - + # Change subscription pattern msgC_subscriber.subscribeTo(msgB) # Subscribe C to B msgD_subscriber.subscribeTo(msgA) # Subscribe D to A @@ -308,8 +308,8 @@ def test_cpp_2_c_msg_subscription_check(): testFailCount += 1 testMessages.append(el + ": msgD_subscriber.isSubscribedTo(msgB) should be False") - - + + if testFailCount == 0: print("PASSED") else: diff --git a/src/tests/test_utilitiesUKF.py b/src/tests/test_utilitiesUKF.py index 166b430e741..a695b66a824 100644 --- a/src/tests/test_utilitiesUKF.py +++ b/src/tests/test_utilitiesUKF.py @@ -60,16 +60,16 @@ def utilities_nominal(filterModule): RVector = inertialUKF.new_doubleArray(len(AMatrix)) AVector = inertialUKF.new_doubleArray(len(AMatrix)) - #RVector = eval(filterModule + '.new_doubleArray(len(AMatrix))') - #AVector = eval(filterModule + '.new_doubleArray(len(AMatrix))') + # Use globals() to map filterModule string to actual imported module + mod = globals()[filterModule] for i in range(len(AMatrix)): - eval(filterModule + '.doubleArray_setitem(AVector, i, AMatrix[i])') - eval(filterModule + '.doubleArray_setitem(RVector, i, 0.0)') + mod.doubleArray_setitem(AVector, i, AMatrix[i]) + mod.doubleArray_setitem(RVector, i, 0.0) - eval(filterModule + '.ukfQRDJustR(AVector, 6, 4, RVector)') + mod.ukfQRDJustR(AVector, 6, 4, RVector) RMatrix = [] for i in range(4 * 4): - RMatrix.append(eval(filterModule + '.doubleArray_getitem(RVector, i)')) + RMatrix.append(mod.doubleArray_getitem(RVector, i)) RBaseNumpy = numpy.array(RMatrix).reshape(4, 4) AMatNumpy = numpy.array(AMatrix).reshape(6, 4) q, r = numpy.linalg.qr(AMatNumpy) @@ -86,16 +86,16 @@ def utilities_nominal(filterModule): -1.08906, 0.0325575, 0.552527, -1.6256, 1.54421, 0.0859311, -1.49159, 1.59683] - RVector = eval(filterModule + '.new_doubleArray(len(AMatrix))') - AVector = eval(filterModule + '.new_doubleArray(len(AMatrix))') + RVector = mod.new_doubleArray(len(AMatrix)) + AVector = mod.new_doubleArray(len(AMatrix)) for i in range(len(AMatrix)): - eval(filterModule + '.doubleArray_setitem(AVector, i, AMatrix[i])') - eval(filterModule + '.doubleArray_setitem(RVector, i, 0.0)') + mod.doubleArray_setitem(AVector, i, AMatrix[i]) + mod.doubleArray_setitem(RVector, i, 0.0) - eval(filterModule + '.ukfQRDJustR(AVector, 5, 4, RVector)') + mod.ukfQRDJustR(AVector, 5, 4, RVector) RMatrix = [] for i in range(4 * 4): - RMatrix.append(eval(filterModule + '.doubleArray_getitem(RVector, i)')) + RMatrix.append(mod.doubleArray_getitem(RVector, i)) RBaseNumpy = numpy.array(RMatrix).reshape(4, 4) AMatNumpy = numpy.array(AMatrix).reshape(5, 4) q, r = numpy.linalg.qr(AMatNumpy) @@ -113,16 +113,16 @@ def utilities_nominal(filterModule): 0.0170, 0, 0, 0.0170] - RVector = eval(filterModule + '.new_doubleArray(len(AMatrix))') - AVector = eval(filterModule + '.new_doubleArray(len(AMatrix))') + RVector = mod.new_doubleArray(len(AMatrix)) + AVector = mod.new_doubleArray(len(AMatrix)) for i in range(len(AMatrix)): - eval(filterModule + '.doubleArray_setitem(AVector, i, AMatrix[i])') - eval(filterModule + '.doubleArray_setitem(RVector, i, 0.0)') + mod.doubleArray_setitem(AVector, i, AMatrix[i]) + mod.doubleArray_setitem(RVector, i, 0.0) - eval(filterModule + '.ukfQRDJustR(AVector, 6, 2, RVector)') + mod.ukfQRDJustR(AVector, 6, 2, RVector) RMatrix = [] for i in range(2 * 2): - RMatrix.append(eval(filterModule + '.doubleArray_getitem(RVector, i)')) + RMatrix.append(mod.doubleArray_getitem(RVector, i)) RBaseNumpy = numpy.array(RMatrix).reshape(2, 2) AMatNumpy = numpy.array(AMatrix).reshape(6, 2) q, r = numpy.linalg.qr(AMatNumpy) @@ -135,41 +135,39 @@ def utilities_nominal(filterModule): testMessages.append("QR Decomposition accuracy failure") LUSourceMat = [8, 1, 6, 3, 5, 7, 4, 9, 2] - LUSVector = eval(filterModule + '.new_doubleArray(len(LUSourceMat))') - LVector = eval(filterModule + '.new_doubleArray(len(LUSourceMat))') - UVector = eval(filterModule + '.new_doubleArray(len(LUSourceMat))') - intSwapVector = eval(filterModule + '.new_intArray(3)') + LUSVector = mod.new_doubleArray(len(LUSourceMat)) + LVector = mod.new_doubleArray(len(LUSourceMat)) + UVector = mod.new_doubleArray(len(LUSourceMat)) + intSwapVector = mod.new_intArray(3) for i in range(len(LUSourceMat)): - eval(filterModule + '.doubleArray_setitem(LUSVector, i, LUSourceMat[i])') - eval(filterModule + '.doubleArray_setitem(UVector, i, 0.0)') - eval(filterModule + '.doubleArray_setitem(LVector, i, 0.0)') + mod.doubleArray_setitem(LUSVector, i, LUSourceMat[i]) + mod.doubleArray_setitem(UVector, i, 0.0) + mod.doubleArray_setitem(LVector, i, 0.0) - exCount = eval(filterModule + '.ukfLUD(LUSVector, 3, 3, LVector, intSwapVector)') - # eval(filterModule + '.ukfUInv(LUSVector, 3, 3, UVector) + exCount = mod.ukfLUD(LUSVector, 3, 3, LVector, intSwapVector) LMatrix = [] UMatrix = [] # UMatrix = [] for i in range(3): - currRow = eval(filterModule + '.intArray_getitem(intSwapVector, i)') + currRow = mod.intArray_getitem(intSwapVector, i) for j in range(3): if (j < i): - LMatrix.append(eval(filterModule + '.doubleArray_getitem(LVector, i * 3 + j)')) + LMatrix.append(mod.doubleArray_getitem(LVector, i * 3 + j)) UMatrix.append(0.0) elif (j > i): LMatrix.append(0.0) - UMatrix.append(eval(filterModule + '.doubleArray_getitem(LVector, i * 3 + j)')) + UMatrix.append(mod.doubleArray_getitem(LVector, i * 3 + j)) else: LMatrix.append(1.0) - UMatrix.append(eval(filterModule + '.doubleArray_getitem(LVector, i * 3 + j)')) - # UMatrix.append(eval(filterModule + '.doubleArray_getitem(UVector, i)) + UMatrix.append(mod.doubleArray_getitem(LVector, i * 3 + j)) LMatrix = numpy.array(LMatrix).reshape(3, 3) UMatrix = numpy.array(UMatrix).reshape(3, 3) outMat = numpy.dot(LMatrix, UMatrix) outMatSwap = numpy.zeros((3, 3)) for i in range(3): - currRow = eval(filterModule + '.intArray_getitem(intSwapVector, i)') + currRow = mod.intArray_getitem(intSwapVector, i) outMatSwap[i, :] = outMat[currRow, :] outMat[currRow, :] = outMat[i, :] LuSourceArray = numpy.array(LUSourceMat).reshape(3, 3) @@ -180,40 +178,40 @@ def utilities_nominal(filterModule): EqnSourceMat = [2.0, 1.0, 3.0, 2.0, 6.0, 8.0, 6.0, 8.0, 18.0] BVector = [1.0, 3.0, 5.0] - EqnVector = eval(filterModule + '.new_doubleArray(len(EqnSourceMat))') - EqnBVector = eval(filterModule + '.new_doubleArray(len(LUSourceMat) // 3)') - EqnOutVector = eval(filterModule + '.new_doubleArray(len(LUSourceMat) // 3)') + EqnVector = mod.new_doubleArray(len(EqnSourceMat)) + EqnBVector = mod.new_doubleArray(len(LUSourceMat) // 3) + EqnOutVector = mod.new_doubleArray(len(LUSourceMat) // 3) for i in range(len(EqnSourceMat)): - eval(filterModule + '.doubleArray_setitem(EqnVector, i, EqnSourceMat[i])') - eval(filterModule + '.doubleArray_setitem(EqnBVector, i // 3, BVector[i // 3])') - eval(filterModule + '.intArray_setitem(intSwapVector, i // 3, 0)') - eval(filterModule + '.doubleArray_setitem(LVector, i, 0.0)') + mod.doubleArray_setitem(EqnVector, i, EqnSourceMat[i]) + mod.doubleArray_setitem(EqnBVector, i // 3, BVector[i // 3]) + mod.intArray_setitem(intSwapVector, i // 3, 0) + mod.doubleArray_setitem(LVector, i, 0.0) - exCount = eval(filterModule + '.ukfLUD(EqnVector, 3, 3, LVector, intSwapVector)') - eval(filterModule + '.ukfLUBckSlv(LVector, 3, 3, intSwapVector, EqnBVector, EqnOutVector)') + exCount = mod.ukfLUD(EqnVector, 3, 3, LVector, intSwapVector) + mod.ukfLUBckSlv(LVector, 3, 3, intSwapVector, EqnBVector, EqnOutVector) expectedSol = [3.0 / 10.0, 4.0 / 10.0, 0.0] errorVal = 0.0 for i in range(3): - errorVal += abs(eval(filterModule + '.doubleArray_getitem(EqnOutVector, i) - expectedSol[i]')) + errorVal += abs(mod.doubleArray_getitem(EqnOutVector, i) - expectedSol[i]) if (errorVal > 1.0E-14): testFailCount += 1 testMessages.append("LU Back-Solve accuracy failure") InvSourceMat = [8, 1, 6, 3, 5, 7, 4, 9, 2] - SourceVector = eval(filterModule + '.new_doubleArray(len(InvSourceMat))') - InvVector = eval(filterModule + '.new_doubleArray(len(InvSourceMat))') + SourceVector = mod.new_doubleArray(len(InvSourceMat)) + InvVector = mod.new_doubleArray(len(InvSourceMat)) for i in range(len(InvSourceMat)): - eval(filterModule + '.doubleArray_setitem(SourceVector, i, InvSourceMat[i])') - eval(filterModule + '.doubleArray_setitem(InvVector, i, 0.0)') + mod.doubleArray_setitem(SourceVector, i, InvSourceMat[i]) + mod.doubleArray_setitem(InvVector, i, 0.0) nRow = int(math.sqrt(len(InvSourceMat))) - eval(filterModule + '.ukfMatInv(SourceVector, nRow, nRow, InvVector)') + mod.ukfMatInv(SourceVector, nRow, nRow, InvVector) InvOut = [] for i in range(len(InvSourceMat)): - InvOut.append(eval(filterModule + '.doubleArray_getitem(InvVector, i)')) + InvOut.append(mod.doubleArray_getitem(InvVector, i)) InvOut = numpy.array(InvOut).reshape(nRow, nRow) expectIdent = numpy.dot(InvOut, numpy.array(InvSourceMat).reshape(3, 3)) @@ -223,16 +221,16 @@ def utilities_nominal(filterModule): testMessages.append("LU Matrix Inverse accuracy failure") cholTestMat = [1.0, 0.0, 0.0, 0.0, 10.0, 5.0, 0.0, 5.0, 10.0] - SourceVector = eval(filterModule + '.new_doubleArray(len(cholTestMat))') - CholVector = eval(filterModule + '.new_doubleArray(len(cholTestMat))') + SourceVector = mod.new_doubleArray(len(cholTestMat)) + CholVector = mod.new_doubleArray(len(cholTestMat)) for i in range(len(cholTestMat)): - eval(filterModule + '.doubleArray_setitem(SourceVector, i, cholTestMat[i])') - eval(filterModule + '.doubleArray_setitem(CholVector, i, 0.0)') + mod.doubleArray_setitem(SourceVector, i, cholTestMat[i]) + mod.doubleArray_setitem(CholVector, i, 0.0) nRow = int(math.sqrt(len(cholTestMat))) - eval(filterModule + '.ukfCholDecomp(SourceVector, nRow, nRow, CholVector)') + mod.ukfCholDecomp(SourceVector, nRow, nRow, CholVector) cholOut = [] for i in range(len(cholTestMat)): - cholOut.append(eval(filterModule + '.doubleArray_getitem(CholVector, i)')) + cholOut.append(mod.doubleArray_getitem(CholVector, i)) cholOut = numpy.array(cholOut).reshape(nRow, nRow) cholComp = numpy.linalg.cholesky(numpy.array(cholTestMat).reshape(nRow, nRow)) @@ -246,17 +244,17 @@ def utilities_nominal(filterModule): 0.0, 1.2672359635912551, 1.7923572711881284, 0.0, 1.0974804773131113, -0.63357997864171967, 1.7920348101787789, 0.033997451205364251] - SourceVector = eval(filterModule + '.new_doubleArray(len(InvSourceMat))') - InvVector = eval(filterModule + '.new_doubleArray(len(InvSourceMat))') + SourceVector = mod.new_doubleArray(len(InvSourceMat)) + InvVector = mod.new_doubleArray(len(InvSourceMat)) for i in range(len(InvSourceMat)): - eval(filterModule + '.doubleArray_setitem(SourceVector, i, InvSourceMat[i])') - eval(filterModule + '.doubleArray_setitem(InvVector, i, 0.0)') + mod.doubleArray_setitem(SourceVector, i, InvSourceMat[i]) + mod.doubleArray_setitem(InvVector, i, 0.0) nRow = int(math.sqrt(len(InvSourceMat))) - eval(filterModule + '.ukfLInv(SourceVector, nRow, nRow, InvVector)') + mod.ukfLInv(SourceVector, nRow, nRow, InvVector) InvOut = [] for i in range(len(InvSourceMat)): - InvOut.append(eval(filterModule + '.doubleArray_getitem(InvVector, i)')) + InvOut.append(mod.doubleArray_getitem(InvVector, i)) InvOut = numpy.array(InvOut).reshape(nRow, nRow) expectIdent = numpy.dot(InvOut, numpy.array(InvSourceMat).reshape(nRow, nRow)) @@ -267,17 +265,17 @@ def utilities_nominal(filterModule): testMessages.append("L Matrix Inverse accuracy failure") InvSourceMat = numpy.transpose(numpy.array(InvSourceMat).reshape(nRow, nRow)).reshape(nRow * nRow).tolist() - SourceVector = eval(filterModule + '.new_doubleArray(len(InvSourceMat))') - InvVector = eval(filterModule + '.new_doubleArray(len(InvSourceMat))') + SourceVector = mod.new_doubleArray(len(InvSourceMat)) + InvVector = mod.new_doubleArray(len(InvSourceMat)) for i in range(len(InvSourceMat)): - eval(filterModule + '.doubleArray_setitem(SourceVector, i, InvSourceMat[i])') - eval(filterModule + '.doubleArray_setitem(InvVector, i, 0.0)') + mod.doubleArray_setitem(SourceVector, i, InvSourceMat[i]) + mod.doubleArray_setitem(InvVector, i, 0.0) nRow = int(math.sqrt(len(InvSourceMat))) - eval(filterModule + '.ukfUInv(SourceVector, nRow, nRow, InvVector)') + mod.ukfUInv(SourceVector, nRow, nRow, InvVector) InvOut = [] for i in range(len(InvSourceMat)): - InvOut.append(eval(filterModule + '.doubleArray_getitem(InvVector, i)')) + InvOut.append(mod.doubleArray_getitem(InvVector, i)) InvOut = numpy.array(InvOut).reshape(nRow, nRow) expectIdent = numpy.dot(InvOut, numpy.array(InvSourceMat).reshape(nRow, nRow)) @@ -304,27 +302,27 @@ def utilities_fault(filterModule): testFailCount = 0 # zero unit test result counter testMessages = [] # create empty list to store test log messages - + mod = globals()[filterModule] LUSourceMat = [8, 1, 6, 3, 5, 7, 4, 9, 2, 1, 9, 3] EqnSourceMat = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] BVector = [0.0, 0.0, 0.0] - LUSVector = eval(filterModule + '.new_doubleArray(len(LUSourceMat))') - LVector = eval(filterModule + '.new_doubleArray(len(LUSourceMat))') - UVector = eval(filterModule + '.new_doubleArray(len(LUSourceMat))') - intSwapVector = eval(filterModule + '.new_intArray(3)') - EqnVector = eval(filterModule + '.new_doubleArray(len(EqnSourceMat))') - EqnBVector = eval(filterModule + '.new_doubleArray(len(LUSourceMat) // 3)') - EqnOutVector = eval(filterModule + '.new_doubleArray(len(LUSourceMat) // 3)') + LUSVector = mod.new_doubleArray(len(LUSourceMat)) + LVector = mod.new_doubleArray(len(LUSourceMat)) + UVector = mod.new_doubleArray(len(LUSourceMat)) + intSwapVector = mod.new_intArray(3) + EqnVector = mod.new_doubleArray(len(EqnSourceMat)) + EqnBVector = mod.new_doubleArray(len(LUSourceMat) // 3) + EqnOutVector = mod.new_doubleArray(len(LUSourceMat) // 3) for i in range(len(LUSourceMat)): - eval(filterModule + '.doubleArray_setitem(LUSVector, i, LUSourceMat[i])') - eval(filterModule + '.doubleArray_setitem(UVector, i, 0.0)') - eval(filterModule + '.doubleArray_setitem(LVector, i, 0.0)') + mod.doubleArray_setitem(LUSVector, i, LUSourceMat[i]) + mod.doubleArray_setitem(UVector, i, 0.0) + mod.doubleArray_setitem(LVector, i, 0.0) - exCount = eval(filterModule + '.ukfLUD(LUSVector, 3, 4, LVector, intSwapVector)') - returnBackSolve = eval(filterModule + '.ukfLUBckSlv(LVector, 3, 4, intSwapVector, EqnBVector, EqnOutVector)') + exCount = mod.ukfLUD(LUSVector, 3, 4, LVector, intSwapVector) + returnBackSolve = mod.ukfLUBckSlv(LVector, 3, 4, intSwapVector, EqnBVector, EqnOutVector) if (exCount >= 0 or exCount is None): testFailCount += 1 @@ -336,13 +334,13 @@ def utilities_fault(filterModule): for i in range(len(EqnSourceMat)): - eval(filterModule + '.doubleArray_setitem(EqnVector, i, EqnSourceMat[i])') - eval(filterModule + '.doubleArray_setitem(EqnBVector, i // 3, BVector[i // 3])') - eval(filterModule + '.intArray_setitem(intSwapVector, i // 3, 0)') - eval(filterModule + '.doubleArray_setitem(LVector, i, 0.0)') + mod.doubleArray_setitem(EqnVector, i, EqnSourceMat[i]) + mod.doubleArray_setitem(EqnBVector, i // 3, BVector[i // 3]) + mod.intArray_setitem(intSwapVector, i // 3, 0) + mod.doubleArray_setitem(LVector, i, 0.0) - exCount = eval(filterModule + '.ukfLUD(EqnVector, 3, 3, LVector, intSwapVector)') - returnBackSolve = eval(filterModule + '.ukfLUBckSlv(LVector, 3, 3, intSwapVector, EqnBVector, EqnOutVector)') + exCount = mod.ukfLUD(EqnVector, 3, 3, LVector, intSwapVector) + returnBackSolve = mod.ukfLUBckSlv(LVector, 3, 3, intSwapVector, EqnBVector, EqnOutVector) if (exCount >= 0 or exCount is None): testFailCount += 1 @@ -354,37 +352,37 @@ def utilities_fault(filterModule): InvSourceMat = [8, 1, 6, 3, 5, 7, 4, 9, 2, 4, 4, 5] - SourceVector = eval(filterModule + '.new_doubleArray(len(InvSourceMat))') - InvVector = eval(filterModule + '.new_doubleArray(len(InvSourceMat))') + SourceVector = mod.new_doubleArray(len(InvSourceMat)) + InvVector = mod.new_doubleArray(len(InvSourceMat)) for i in range(len(InvSourceMat)): - eval(filterModule + '.doubleArray_setitem(SourceVector, i, InvSourceMat[i])') - eval(filterModule + '.doubleArray_setitem(InvVector, i, 0.0)') - returnInv = eval(filterModule + '.ukfMatInv(SourceVector, 3, 4, InvVector)') + mod.doubleArray_setitem(SourceVector, i, InvSourceMat[i]) + mod.doubleArray_setitem(InvVector, i, 0.0) + returnInv = mod.ukfMatInv(SourceVector, 3, 4, InvVector) if (returnInv >=0 or returnInv is None): testFailCount += 1 testMessages.append("LU Matrix Inverse accuracy failure") cholTestMatLong = [1.0, 0.0, 0.0, 0.0, 10.0, 5.0, 0.0, 5.0, 10.0, 10.0, 5.0, 10.0] - SourceVector = eval(filterModule + '.new_doubleArray(len(cholTestMatLong))') - CholVector = eval(filterModule + '.new_doubleArray(len(cholTestMatLong))') + SourceVector = mod.new_doubleArray(len(cholTestMatLong)) + CholVector = mod.new_doubleArray(len(cholTestMatLong)) for i in range(len(cholTestMatLong)): - eval(filterModule + '.doubleArray_setitem(SourceVector, i, cholTestMatLong[i])') - eval(filterModule + '.doubleArray_setitem(CholVector, i, 0.0)') - returnChol = eval(filterModule + '.ukfCholDecomp(SourceVector, 3, 4, CholVector)') + mod.doubleArray_setitem(SourceVector, i, cholTestMatLong[i]) + mod.doubleArray_setitem(CholVector, i, 0.0) + returnChol = mod.ukfCholDecomp(SourceVector, 3, 4, CholVector) if (returnChol >=0 or returnChol is None): testFailCount += 1 testMessages.append("Cholesky Matrix Decomposition Size failure") cholTestMat = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] - SourceVector = eval(filterModule + '.new_doubleArray(len(cholTestMat))') - CholVector = eval(filterModule + '.new_doubleArray(len(cholTestMat))') + SourceVector = mod.new_doubleArray(len(cholTestMat)) + CholVector = mod.new_doubleArray(len(cholTestMat)) for i in range(len(cholTestMat)): - eval(filterModule + '.doubleArray_setitem(SourceVector, i, cholTestMat[i])') - eval(filterModule + '.doubleArray_setitem(CholVector, i, 0.0)') + mod.doubleArray_setitem(SourceVector, i, cholTestMat[i]) + mod.doubleArray_setitem(CholVector, i, 0.0) nRow = int(math.sqrt(len(cholTestMat))) - returnChol = eval(filterModule + '.ukfCholDecomp(SourceVector, nRow, nRow, CholVector)') + returnChol = mod.ukfCholDecomp(SourceVector, nRow, nRow, CholVector) if (returnChol >=0 or returnChol is None): testFailCount += 1 @@ -392,14 +390,14 @@ def utilities_fault(filterModule): rMat = [1.0, 0.0, 0.0, 0.0, 10.0, 5.0, 0.0, 5.0, 10.0] xVec = [100.0, 0.0, 0.0] - inRMat = eval(filterModule + '.new_doubleArray(len(rMat))') - inXVec = eval(filterModule + '.new_doubleArray(len(xVec))') + inRMat = mod.new_doubleArray(len(rMat)) + inXVec = mod.new_doubleArray(len(xVec)) for i in range(len(rMat)): - eval(filterModule + '.doubleArray_setitem(inRMat, i, rMat[i])') + mod.doubleArray_setitem(inRMat, i, rMat[i]) for i in range(len(xVec)): - eval(filterModule + '.doubleArray_setitem(inXVec, i, xVec[i])') + mod.doubleArray_setitem(inXVec, i, xVec[i]) nRow = int(math.sqrt(len(rMat))) - returnDown = eval(filterModule + '.ukfCholDownDate(inRMat, inXVec, -100, 3, CholVector)') + returnDown = mod.ukfCholDownDate(inRMat, inXVec, -100, 3, CholVector) if (returnChol >=0 or returnChol is None): testFailCount += 1 @@ -410,13 +408,13 @@ def utilities_fault(filterModule): 0.0, 1.2672359635912551, 1.7923572711881284, 0.0, 1., 1.0974804773131113, -0.63357997864171967, 1.7920348101787789, 0.033997451205364251, 1.] - SourceVector = eval(filterModule + '.new_doubleArray(len(InvSourceMatRect))') - InvVector = eval(filterModule + '.new_doubleArray(len(InvSourceMatRect))') + SourceVector = mod.new_doubleArray(len(InvSourceMatRect)) + InvVector = mod.new_doubleArray(len(InvSourceMatRect)) for i in range(len(InvSourceMatRect)): - eval(filterModule + '.doubleArray_setitem(SourceVector, i, InvSourceMatRect[i])') - eval(filterModule + '.doubleArray_setitem(InvVector, i, 0.0)') + mod.doubleArray_setitem(SourceVector, i, InvSourceMatRect[i]) + mod.doubleArray_setitem(InvVector, i, 0.0) nRow = int(math.sqrt(len(InvSourceMatRect))) - returnLinv = eval(filterModule + '.ukfLInv(SourceVector, nRow, nRow, InvVector)') + returnLinv = mod.ukfLInv(SourceVector, nRow, nRow, InvVector) if (returnLinv >= 0 or returnLinv is None): testFailCount += 1 @@ -427,37 +425,37 @@ def utilities_fault(filterModule): 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,] - SourceVector = eval(filterModule + '.new_doubleArray(len(InvSourceMat0))') - InvVector = eval(filterModule + '.new_doubleArray(len(InvSourceMat0))') + SourceVector = mod.new_doubleArray(len(InvSourceMat0)) + InvVector = mod.new_doubleArray(len(InvSourceMat0)) for i in range(len(InvSourceMat0)): - eval(filterModule + '.doubleArray_setitem(SourceVector, i, InvSourceMat0[i])') - eval(filterModule + '.doubleArray_setitem(InvVector, i, 0.0)') + mod.doubleArray_setitem(SourceVector, i, InvSourceMat0[i]) + mod.doubleArray_setitem(InvVector, i, 0.0) nRow = int(math.sqrt(len(InvSourceMat0))) - returnLinv = eval(filterModule + '.ukfLInv(SourceVector, nRow, nRow, InvVector)') + returnLinv = mod.ukfLInv(SourceVector, nRow, nRow, InvVector) if (returnLinv >= 0 or returnLinv is None): testFailCount += 1 testMessages.append("L Matrix Inverse didn't catch sign error") - SourceVector = eval(filterModule + '.new_doubleArray(len(InvSourceMat0))') - InvVector = eval(filterModule + '.new_doubleArray(len(InvSourceMat0))') + SourceVector = mod.new_doubleArray(len(InvSourceMat0)) + InvVector = mod.new_doubleArray(len(InvSourceMat0)) for i in range(len(InvSourceMat0)): - eval(filterModule + '.doubleArray_setitem(SourceVector, i, InvSourceMat0[i])') - eval(filterModule + '.doubleArray_setitem(InvVector, i, 0.0)') + mod.doubleArray_setitem(SourceVector, i, InvSourceMat0[i]) + mod.doubleArray_setitem(InvVector, i, 0.0) nRow = int(math.sqrt(len(InvSourceMat0))) - returnU = eval(filterModule + '.ukfUInv(SourceVector, nRow, nRow, InvVector)') + returnU = mod.ukfUInv(SourceVector, nRow, nRow, InvVector) if (returnU >= 0 or returnU is None): testFailCount += 1 testMessages.append("U Matrix Inverse didn't catch non square matrix") - SourceVector = eval(filterModule + '.new_doubleArray(len(InvSourceMat0))') - InvVector = eval(filterModule + '.new_doubleArray(len(InvSourceMat0))') + SourceVector = mod.new_doubleArray(len(InvSourceMat0)) + InvVector = mod.new_doubleArray(len(InvSourceMat0)) for i in range(len(InvSourceMat0)): - eval(filterModule + '.doubleArray_setitem(SourceVector, i, InvSourceMat0[i])') - eval(filterModule + '.doubleArray_setitem(InvVector, i, 0.0)') + mod.doubleArray_setitem(SourceVector, i, InvSourceMat0[i]) + mod.doubleArray_setitem(InvVector, i, 0.0) nRow = int(math.sqrt(len(InvSourceMat0))) - returnU = eval(filterModule + '.ukfUInv(SourceVector, nRow, nRow, InvVector)') + returnU = mod.ukfUInv(SourceVector, nRow, nRow, InvVector) if (returnU >= 0 or returnU is None): testFailCount += 1 diff --git a/src/utilities/MonteCarlo/Controller.py b/src/utilities/MonteCarlo/Controller.py index 4c106f16cef..d8738081bcb 100644 --- a/src/utilities/MonteCarlo/Controller.py +++ b/src/utilities/MonteCarlo/Controller.py @@ -826,10 +826,9 @@ def __call__(cls, params): # apply the dispersions and the random seeds for variable, value in list(modifications.items()): - disperseStatement = "simInstance." + variable + "=" + value if simParams.verbose: - print("Executing parameter modification -> ", disperseStatement) - exec(disperseStatement) + print(f"Setting attribute {variable} to {value} on simInstance") + setattr(simInstance, variable, value) # setup data logging if len(simParams.retentionPolicies) > 0: @@ -900,7 +899,7 @@ def disperseSeeds(simInstance): rand = str(random.randint(0, 1 << 32 - 1)) try: execStatement = "simInstance." + taskVar + "=" + str(rand) - exec(execStatement) # if this fails don't add to the list of modification + setattr(simInstance, taskVar, rand) # if this fails don't add to the list of modification randomSeeds[taskVar] = rand except: pass @@ -920,5 +919,4 @@ def populateSeeds(simInstance, modifications): for variable, value in modifications.items(): if ".RNGSeed" in variable: rngStatement = "simInstance." + variable + "=" + value - exec(rngStatement) - + setattr(simInstance, variable, value) diff --git a/src/utilities/MonteCarlo/Dispersions.py b/src/utilities/MonteCarlo/Dispersions.py index fea324ec44b..a4cd4cc3579 100644 --- a/src/utilities/MonteCarlo/Dispersions.py +++ b/src/utilities/MonteCarlo/Dispersions.py @@ -93,7 +93,7 @@ def generate(self, sim): class VectorVariableDispersion(object): __metaclass__ = abc.ABCMeta - + def __init__(self, varName, bounds): self.varName = varName self.bounds = bounds @@ -209,7 +209,7 @@ def __init__(self, varName, bounds=None): self.bounds = ([-1.0, 1.0]) # defines a hard floor/ceiling def generate(self, sim): - vector = eval('sim.' + self.varName) + vector = getattr(sim, self.varName) dispValue = self.perturbCartesianVectorUniform(vector) return dispValue @@ -221,7 +221,7 @@ def __init__(self, varName, mean=0.0, stdDeviation=0.5, bounds=None): self.bounds = ([-1.0, 1.0]) # defines a hard floor/ceiling def generate(self, sim): - vector = eval('sim.' + self.varName) + vector = getattr(sim, self.varName) dispValue = self.perturbCartesianVectorNormal(vector, self.mean, self.stdDeviation) return dispValue @@ -243,7 +243,7 @@ def __init__(self, varName, phiBoundsOffNom=None, thetaBoundsOffNom=None): def generate(self, sim=None): # Note this dispersion is applied off of the nominal - vectorCart = eval('sim.' + self.varName) + vectorCart = getattr(sim, self.varName) vectorCart = vectorCart/np.linalg.norm(vectorCart) vectorSphere = self.cart2Spherical(vectorCart) @@ -291,7 +291,7 @@ def __init__(self, varName, thetaStd = np.pi/3.0, phiStd=np.pi/3.0, thetaBoundsO self.magnitude = [] def generate(self, sim=None): - vectorCart = eval('sim.' + self.varName) + vectorCart = getattr(sim, self.varName) vectorCart = vectorCart/np.linalg.norm(vectorCart) vectorSphere = self.cart2Spherical(vectorCart) @@ -394,7 +394,8 @@ def generate(self, sim=None): separator = '.' thrusterObject = getattr(sim, self.varNameComponents[0]) totalVar = separator.join(self.varNameComponents[0:-1]) - dirVec = eval('sim.' + totalVar + '.thrDir_B') + simObject = getattr(sim, totalVar) # sim.totalVar + dirVec = getattr(simObject, 'thrDir_B') # sim.totalVar.thrDir_B angle = np.random.normal(0, self.phiStd, 1) dirVec = np.array(dirVec).reshape(3).tolist() dispVec = self.perturbVectorByAngle(dirVec, angle) @@ -477,7 +478,11 @@ def generate(self, sim=None): return else: vehDynObject = getattr(sim, self.varNameComponents[0]) - I = np.array(eval('sim.' + self.varName)).reshape(3, 3) + parts = self.varName.split('.') + attr = sim + for part in parts: + attr = getattr(attr, part) + I = np.array(attr).reshape(3, 3) # generate random values for the diagonals temp = [] @@ -560,10 +565,12 @@ def generate(self, sim=None): elems = orbitalMotion.ClassicElements for key in self.oeDict.keys(): if self.oeDict[key] is not None and key != "mu": - exec("elems."+ key + " = np.random." + self.oeDict[key][0] + "(" + str(self.oeDict[key][1]) + ', ' + str(self.oeDict[key][2]) + ")") + distribution = getattr(np.random, self.oeDict[key][0]) + random_value = distribution(self.oeDict[key][1], self.oeDict[key][2]) + setattr(elems, key, random_value) else: if key != "mu": - exec("elems." + key + " = 0.") + setattr(elems, key, 0.0) if elems.e < 0: elems.e = 0 r, v =orbitalMotion.elem2rv_parab( self.oeDict["mu"], elems) diff --git a/src/utilities/SimulationBaseClass.py b/src/utilities/SimulationBaseClass.py index ae26d18cb74..6dae750ead3 100755 --- a/src/utilities/SimulationBaseClass.py +++ b/src/utilities/SimulationBaseClass.py @@ -59,8 +59,9 @@ def __init__(self, eventName, eventRate=int(1E9), eventActive=False, self.terminal = terminal def methodizeEvent(self): - if self.checkCall != None: + if self.checkCall is not None: return + funcString = 'def EVENT_check_' + self.eventName + '(self):\n' funcString += ' if(' for condValue in self.conditionList: @@ -69,15 +70,18 @@ def methodizeEvent(self): funcString += ' return 1\n' funcString += ' return 0' - exec (funcString) - self.checkCall = eval('EVENT_check_' + self.eventName) + local_namespace = {} + exec(funcString, globals(), local_namespace) + self.checkCall = local_namespace['EVENT_check_' + self.eventName] + funcString = 'def EVENT_operate_' + self.eventName + '(self):\n' for actionValue in self.actionList: - funcString += ' ' - funcString += actionValue + '\n' + funcString += ' ' + actionValue + '\n' funcString += ' return 0' - exec (funcString) - self.operateCall = eval('EVENT_operate_' + self.eventName) + + local_namespace = {} + exec(funcString, globals(), local_namespace) + self.operateCall = local_namespace['EVENT_operate_' + self.eventName] def checkEvent(self, parentSim): nextTime = int(-1) diff --git a/src/utilities/datasheet_RW.py b/src/utilities/datasheet_RW.py index 378225855cc..f3f6f045829 100644 --- a/src/utilities/datasheet_RW.py +++ b/src/utilities/datasheet_RW.py @@ -61,7 +61,10 @@ def Honeywell_HR16(maxMomentum_level): else: raise ValueError('Honeywell_HR16(maxMomentum_level) only has arg options maxMomentum = [large, medium, small]') - maxMomentum = eval('maxMomentum_'+ maxMomentum_level) + maxMomentum = globals().get('maxMomentum_' + maxMomentum_level) + if maxMomentum is None: + raise ValueError(f"maxMomentum_{maxMomentum_level} not found") + return (Omega_max, u_max, u_min, u_f, mass, U_s, U_d, maxMomentum) diff --git a/src/utilities/simIncludeRW.py b/src/utilities/simIncludeRW.py index 4e25feb51f7..f5323aec84d 100755 --- a/src/utilities/simIncludeRW.py +++ b/src/utilities/simIncludeRW.py @@ -169,7 +169,7 @@ def create(self, rwType, gsHat_B, **kwargs): # populate the RW object with the type specific parameters try: - eval('self.' + rwType + '(RW)') + getattr(self, rwType)(RW) except: print('ERROR: RW type ' + rwType + ' is not implemented') exit(1) diff --git a/src/utilities/simIncludeThruster.py b/src/utilities/simIncludeThruster.py index 0c3a39c80eb..1685c687b26 100755 --- a/src/utilities/simIncludeThruster.py +++ b/src/utilities/simIncludeThruster.py @@ -87,7 +87,7 @@ def create(self, thrusterType, r_B, tHat_B, **kwargs): # populate the thruster object with the type specific parameters try: - eval('self.' + thrusterType + '(TH)') + getattr(self, thrusterType)(TH) except: print('ERROR: Thruster type ' + thrusterType + ' is not implemented') exit(1)