1- # fork of https://github.com/encode/starlette/blob/master/starlette/middleware/gzip.py
21import gzip
32import io
43import logging
54import json
5+ import copy
66
77from typing import NoReturn , Tuple
88
@@ -49,8 +49,9 @@ def rocketpy_encoder(obj, config: DiscretizeConfig = DiscretizeConfig()):
4949 """
5050 Encode a RocketPy object using official RocketPy encoders.
5151
52- This function discretizes callable Function attributes and then uses
53- RocketPy's official RocketPyEncoder for complete object serialization.
52+ This function creates a shallow copy of the object, discretizes callable Function
53+ attributes on the copy, and then uses RocketPy's official RocketPyEncoder for
54+ complete object serialization. The original object remains unchanged.
5455
5556 Args:
5657 obj: RocketPy object (Environment, Motor, Rocket, Flight)
@@ -60,22 +61,20 @@ def rocketpy_encoder(obj, config: DiscretizeConfig = DiscretizeConfig()):
6061 Dictionary of encoded attributes
6162 """
6263
63- for attr_name in dir (obj ):
64+ # Create a shallow copy to avoid mutating the original object
65+ obj_copy = copy .copy (obj )
66+
67+ for attr_name in dir (obj_copy ):
6468 if attr_name .startswith ('_' ):
6569 continue
6670
6771 try :
68- attr_value = getattr (obj , attr_name )
72+ attr_value = getattr (obj_copy , attr_name )
6973 except Exception :
7074 continue
7175
7276 if callable (attr_value ) and isinstance (attr_value , Function ):
7377 try :
74- # Create a new Function from the source to avoid mutating the original object.
75- # This is important because:
76- # 1. The original RocketPy object should remain unchanged for reusability
77- # 2. Multiple simulations might need different discretization parameters
78- # 3. Other parts of the system might depend on the original continuous function
7978 discretized_func = Function (attr_value .source )
8079 discretized_func .set_discrete (
8180 lower = config .bounds [0 ],
@@ -84,14 +83,14 @@ def rocketpy_encoder(obj, config: DiscretizeConfig = DiscretizeConfig()):
8483 mutate_self = True ,
8584 )
8685
87- setattr (obj , attr_name , discretized_func )
86+ setattr (obj_copy , attr_name , discretized_func )
8887
8988 except Exception as e :
9089 logger .warning (f"Failed to discretize { attr_name } : { e } " )
9190
9291 try :
9392 json_str = json .dumps (
94- obj ,
93+ obj_copy ,
9594 cls = RocketPyEncoder ,
9695 include_outputs = True ,
9796 include_function_data = True ,
@@ -100,10 +99,10 @@ def rocketpy_encoder(obj, config: DiscretizeConfig = DiscretizeConfig()):
10099 except Exception as e :
101100 logger .warning (f"Failed to encode with RocketPyEncoder: { e } " )
102101 attributes = {}
103- for attr_name in dir (obj ):
102+ for attr_name in dir (obj_copy ):
104103 if not attr_name .startswith ('_' ):
105104 try :
106- attr_value = getattr (obj , attr_name )
105+ attr_value = getattr (obj_copy , attr_name )
107106 if not callable (attr_value ):
108107 attributes [attr_name ] = str (attr_value )
109108 except Exception :
@@ -136,6 +135,7 @@ async def __call__(
136135
137136
138137class GZipResponder :
138+ # fork of https://github.com/encode/starlette/blob/master/starlette/middleware/gzip.py
139139 def __init__ (
140140 self , app : ASGIApp , minimum_size : int , compresslevel : int = 9
141141 ) -> None :
0 commit comments