44 ControllerBase ,
55 controller_exception_handler ,
66)
7- from src .views .flight import FlightSimulation , FlightCreated
7+ from src .views .flight import FlightSimulation , FlightCreated , FlightImported
88from src .models .flight import (
99 FlightModel ,
1010 FlightWithReferencesRequest ,
1111)
1212from src .models .environment import EnvironmentModel
13+ from src .models .motor import MotorModel
1314from src .models .rocket import RocketModel
1415from src .repositories .interface import RepositoryInterface
1516from src .services .flight import FlightService
@@ -22,6 +23,7 @@ class FlightController(ControllerBase):
2223 Enables:
2324 - Simulation of a RocketPy Flight.
2425 - CRUD for Flight BaseApiModel.
26+ - Import/export as portable .rpy files and Jupyter notebooks.
2527 """
2628
2729 def __init__ (self ):
@@ -122,25 +124,26 @@ async def update_rocket_by_flight_id(
122124 return
123125
124126 @controller_exception_handler
125- async def get_rocketpy_flight_binary (
127+ async def get_rocketpy_flight_rpy (
126128 self ,
127129 flight_id : str ,
128130 ) -> bytes :
129131 """
130- Get rocketpy.flight as dill binary .
132+ Get rocketpy.flight as a portable ``.rpy`` JSON file .
131133
132134 Args:
133135 flight_id: str
134136
135137 Returns:
136- bytes
138+ bytes (UTF-8 encoded JSON)
137139
138140 Raises:
139- HTTP 404 Not Found: If the flight is not found in the database.
141+ HTTP 404 Not Found: If the flight is not found
142+ in the database.
140143 """
141144 flight = await self .get_flight_by_id (flight_id )
142145 flight_service = FlightService .from_flight_model (flight .flight )
143- return flight_service .get_flight_binary ()
146+ return flight_service .get_flight_rpy ()
144147
145148 @controller_exception_handler
146149 async def get_flight_simulation (
@@ -162,3 +165,71 @@ async def get_flight_simulation(
162165 flight = await self .get_flight_by_id (flight_id )
163166 flight_service = FlightService .from_flight_model (flight .flight )
164167 return flight_service .get_flight_simulation ()
168+
169+ async def _persist_model (self , model_cls , model_instance ) -> str :
170+ repo_cls = RepositoryInterface .get_model_repo (model_cls )
171+ async with repo_cls () as repo :
172+ creator = getattr (repo , f"create_{ model_cls .NAME } " )
173+ return await creator (model_instance )
174+
175+ @controller_exception_handler
176+ async def import_flight_from_rpy (
177+ self ,
178+ content : bytes ,
179+ ) -> FlightImported :
180+ """
181+ Import a ``.rpy`` JSON file: decompose the RocketPy Flight
182+ into Environment, Motor, Rocket and Flight models, persist
183+ each one via the normal CRUD pipeline, and return all IDs.
184+
185+ Args:
186+ content: raw bytes of a ``.rpy`` JSON file.
187+
188+ Returns:
189+ FlightImported with environment_id, motor_id,
190+ rocket_id, and flight_id.
191+
192+ Raises:
193+ HTTP 422: If the file is not a valid ``.rpy`` Flight.
194+ """
195+ try :
196+ flight_service = FlightService .from_rpy (content )
197+ except Exception as exc :
198+ raise HTTPException (
199+ status_code = status .HTTP_422_UNPROCESSABLE_ENTITY ,
200+ detail = f"Invalid .rpy file: { exc } " ,
201+ ) from exc
202+
203+ env , motor , rocket , flight = flight_service .extract_models ()
204+
205+ env_id = await self ._persist_model (EnvironmentModel , env )
206+ motor_id = await self ._persist_model (MotorModel , motor )
207+ rocket_id = await self ._persist_model (RocketModel , rocket )
208+ flight_id = await self ._persist_model (FlightModel , flight )
209+
210+ return FlightImported (
211+ flight_id = flight_id ,
212+ rocket_id = rocket_id ,
213+ motor_id = motor_id ,
214+ environment_id = env_id ,
215+ )
216+
217+ @controller_exception_handler
218+ async def get_flight_notebook (
219+ self ,
220+ flight_id : str ,
221+ ) -> dict :
222+ """
223+ Generate a Jupyter notebook for a persisted flight.
224+
225+ Args:
226+ flight_id: str
227+
228+ Returns:
229+ dict representing a valid .ipynb.
230+
231+ Raises:
232+ HTTP 404 Not Found: If the flight does not exist.
233+ """
234+ await self .get_flight_by_id (flight_id )
235+ return FlightService .generate_notebook (flight_id )
0 commit comments