diff --git a/lib/api.py b/lib/api.py
index 3716ddd..7bbdea8 100644
--- a/lib/api.py
+++ b/lib/api.py
@@ -46,7 +46,7 @@ def custom_openapi():
return app.openapi_schema
openapi_schema = get_openapi(
title="RocketPy Infinity-API",
- version="2.0.0",
+ version="2.1.0",
description=(
"
RocketPy Infinity-API is a RESTful Open API for RocketPy, a rocket flight simulator.
"
"
"
diff --git a/lib/models/rocket.py b/lib/models/rocket.py
index 54ed105..fb46c2b 100644
--- a/lib/models/rocket.py
+++ b/lib/models/rocket.py
@@ -21,7 +21,7 @@ class Parachute(BaseModel):
cd_s: float = 10
sampling_rate: int = 105
lag: float = 1.5
- trigger: Union[str, float] = "lambda p, h, y: y[5] < 0 and h < 800"
+ trigger: Union[str, float] = "apogee"
noise: Tuple[float, float, float] = (0, 8.3, 0.5)
diff --git a/lib/services/rocket.py b/lib/services/rocket.py
index 572d7a2..32d7729 100644
--- a/lib/services/rocket.py
+++ b/lib/services/rocket.py
@@ -1,4 +1,3 @@
-import ast
from typing import Self
import dill
@@ -21,10 +20,6 @@
from lib.views.rocket import RocketSummary
-class InvalidParachuteTrigger(Exception):
- """Exception raised for invalid parachute trigger expressions."""
-
-
class RocketService:
_rocket: RocketPyRocket
@@ -81,14 +76,7 @@ def from_rocket_model(cls, rocket: Rocket) -> Self:
# Parachutes
for parachute in rocket.parachutes:
- if cls.check_parachute_trigger(
- trigger_expression := parachute.trigger
- ):
- parachute.trigger = eval( # pylint: disable=eval-used
- trigger_expression,
- {"__builtins__": None},
- {"apogee": "apogee"},
- )
+ if cls.check_parachute_trigger(parachute.trigger):
rocketpy_parachute = cls.get_rocketpy_parachute(parachute)
rocketpy_rocket.parachutes.append(rocketpy_parachute)
else:
@@ -219,67 +207,19 @@ def get_rocketpy_parachute(parachute: Parachute) -> RocketPyParachute:
return rocketpy_parachute
@staticmethod
- def check_parachute_trigger(expression) -> bool:
+ def check_parachute_trigger(trigger) -> bool:
"""
Check if the trigger expression is valid.
Args:
- expression: str
+ trigger: str | float
Returns:
bool: True if the expression is valid, False otherwise.
"""
- # Parsing the expression into an AST
- try:
- parsed_expression = ast.parse(expression, mode="eval")
- except SyntaxError as e:
- raise InvalidParachuteTrigger(
- f"Invalid expression syntax: {str(e)}"
- ) from None
-
- # Constant case (supported after beta v1)
- if isinstance(parsed_expression.body, ast.Constant):
+ if trigger == "apogee":
return True
- # Name case (supported after beta v1)
- if (
- isinstance(parsed_expression.body, ast.Name)
- and parsed_expression.body.id == "apogee"
- ):
+ if isinstance(trigger, (int, float)):
return True
-
- # Validating the expression structure
- if not isinstance(parsed_expression.body, ast.Lambda):
- raise InvalidParachuteTrigger(
- "Invalid expression structure: not a lambda."
- ) from None
-
- lambda_node = parsed_expression.body
- if len(lambda_node.args.args) != 3:
- raise InvalidParachuteTrigger(
- "Invalid expression structure: lambda should have 3 arguments."
- ) from None
-
- if not isinstance(lambda_node.body, ast.Compare):
- try:
- for operand in lambda_node.body.values:
- if not isinstance(operand, ast.Compare):
- raise InvalidParachuteTrigger(
- "Invalid expression structure: not a Compare."
- ) from None
- except AttributeError:
- raise InvalidParachuteTrigger(
- "Invalid expression structure: not a Compare."
- ) from None
-
- # Restricting access to functions or attributes
- for node in ast.walk(lambda_node):
- if isinstance(node, ast.Call):
- raise InvalidParachuteTrigger(
- "Calling functions is not allowed in the expression."
- ) from None
- if isinstance(node, ast.Attribute):
- raise InvalidParachuteTrigger(
- "Accessing attributes is not allowed in the expression."
- ) from None
- return True
+ return False
diff --git a/lib/settings/gunicorn.py b/lib/settings/gunicorn.py
index 34e398c..39b0b19 100644
--- a/lib/settings/gunicorn.py
+++ b/lib/settings/gunicorn.py
@@ -7,7 +7,7 @@ def post_fork(server, worker): # pylint: disable=unused-argument
uptrace.configure_opentelemetry(
dsn=Secrets.get_secret("UPTRACE_DSN"),
service_name="infinity-api",
- service_version="2.0.0",
+ service_version="2.1.0",
deployment_environment="production",
)
from lib.api import ( # pylint: disable=import-outside-toplevel
diff --git a/pyproject.toml b/pyproject.toml
index 1d58e9b..78929dd 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -7,7 +7,7 @@ dependencies = {file = ["requirements.txt"]}
[project]
name = "Infinity-API"
-version = "2.0.0"
+version = "2.1.0"
description = "RESTFULL open API for rocketpy"
dynamic = ["dependencies"]
requires-python = ">=3.12"