@@ -91,44 +91,131 @@ def get_active(self, **kwargs) -> dict: # noqa: D102
9191
9292 @protect_grpc
9393 def upload_file (self , ** kwargs ) -> dict : # noqa: D102
94- from ansys .api .discovery .v1 .commands .file_pb2 import OpenRequest
9594 from pathlib import Path
9695 from typing import TYPE_CHECKING , Generator
9796
97+ from ansys .api .discovery .v1 .commands .file_pb2 import OpenRequest
9898 import ansys .geometry .core .connection .defaults as pygeom_defaults
9999
100100 if TYPE_CHECKING : # pragma: no cover
101101 from ansys .geometry .core .misc .options import ImportOptions
102102
103+ # ---- 1) Extract and log kwargs ----
104+ raw_file_path = kwargs .get ("file_path" )
105+ open_file = kwargs .get ("open_file" , False )
106+ import_options = kwargs .get ("import_options" ) # may be None
107+
108+ print ("[upload_file] raw_file_path =" , raw_file_path )
109+ print ("[upload_file] open_file =" , open_file )
110+ print ("[upload_file] import_opts =" , type (import_options ))
111+
112+ if raw_file_path is None :
113+ raise ValueError ("[upload_file] 'file_path' kwarg is required" )
114+
115+ file_path = Path (raw_file_path )
116+
117+ # ---- 2) Validate file existence & readability ----
118+ if not file_path .exists ():
119+ raise FileNotFoundError (f"[upload_file] File does not exist: { file_path !r} " )
120+ if not file_path .is_file ():
121+ raise ValueError (f"[upload_file] Path is not a file: { file_path !r} " )
122+
123+ try :
124+ size = file_path .stat ().st_size
125+ except Exception as e :
126+ print ("[upload_file] Error stating file:" , e )
127+ raise
128+
129+ print (f"[upload_file] File exists, size = { size } bytes" )
130+
131+ # ---- 3) Safe helper for import_options.to_dict() ----
132+ def import_options_to_dict (import_opts : "ImportOptions | None" ):
133+ if import_opts is None :
134+ print ("[upload_file] import_options is None → using empty dict" )
135+ return {}
136+ try :
137+ d = import_opts .to_dict ()
138+ print ("[upload_file] import_options.to_dict() succeeded" )
139+ return d
140+ except Exception as e :
141+ print ("[upload_file] ERROR in import_options.to_dict():" , repr (e ))
142+ import traceback
143+ traceback .print_exc ()
144+ # Re-raise so we see the real cause instead of UNKNOWN / iterating requests
145+ raise
146+
147+ # Precompute once so we don't repeat this in each chunk
148+ import_options_dict = import_options_to_dict (import_options )
149+
150+ # ---- 4) Request generator with strong logging & exception surfacing ----
103151 def request_generator (
104- file_path : Path , open_file : bool , import_options : "ImportOptions"
152+ file_path : Path , open_file : bool , import_options_dict : dict
105153 ) -> Generator [OpenRequest , None , None ]:
106154 """Generate requests for streaming file upload."""
155+ import traceback
156+
107157 msg_buffer = 5 * 1024 # 5KB - for additional message data
108158 if pygeom_defaults .MAX_MESSAGE_LENGTH - msg_buffer < 0 : # pragma: no cover
109- raise ValueError ("MAX_MESSAGE_LENGTH is too small for file upload." )
159+ raise ValueError (
160+ "[upload_file] MAX_MESSAGE_LENGTH is too small for file upload"
161+ )
110162
111163 chunk_size = pygeom_defaults .MAX_MESSAGE_LENGTH - msg_buffer
112- with Path .open (file_path , "rb" ) as file :
113- while chunk := file .read (chunk_size ):
114- yield OpenRequest (
115- data = chunk ,
116- file_name = file_path .name ,
117- open = open_file ,
118- import_options = import_options .to_dict (),
119- )
164+ print (f"[upload_file] Using chunk_size = { chunk_size } bytes" )
165+
166+ try :
167+ with file_path .open ("rb" ) as file :
168+ chunk_index = 0
169+ while True :
170+ chunk = file .read (chunk_size )
171+ if not chunk :
172+ print ("[upload_file] No more data to read, stopping generator" )
173+ break
174+
175+ print (
176+ f"[upload_file] Yielding chunk { chunk_index } , "
177+ f"len={ len (chunk )} "
178+ )
179+
180+ yield OpenRequest (
181+ data = chunk ,
182+
183+ import_options = import_options_dict ,
184+ )
185+ chunk_index += 1
186+ except Exception as e :
187+ print ("[upload_file] EXCEPTION inside request_generator:" )
188+ traceback .print_exc ()
189+ # Re-raise so gRPC wraps it, but you still see the root traceback
190+ raise
191+
192+ # ---- 5) Call the gRPC service, with extra logging ----
193+ gen = request_generator (
194+ file_path = file_path ,
195+ open_file = open_file ,
196+ import_options_dict = import_options_dict ,
197+ )
120198
199+ from grpc import RpcError
121200
201+ try :
202+ print ("[upload_file] Calling file_stub.Open(...)" )
203+ response = self .file_stub .Open (gen )
204+ print ("[upload_file] file_stub.Open(...) returned successfully" )
205+ except RpcError as rpc_exc :
206+ # This is what you currently see as UNKNOWN / Exception iterating requests
207+ print ("[upload_file] RpcError caught in upload_file:" )
208+ print (" code :" , rpc_exc .code ())
209+ print (" details:" , rpc_exc .details ())
210+ import traceback
122211
123- # Call the gRPC service
124- response = self . file_stub . Open ( request_generator (
125- file_path = kwargs [ "file_path" ],
126- open_file = kwargs [ "open_file" ],
127- import_options = kwargs [ "import_options" ],
128- ))
212+ traceback . print_exc ()
213+ # Re-raise so the higher-level wrapper (protect_grpc) can do its thing
214+ raise
215+
216+ # ---- 6) Return the response - formatted as a dictionary ----
217+ return { "file_path" : response . file_path }
129218
130- # Return the response - formatted as a dictionary
131- return {"file_path" : response .file_path }
132219
133220 @protect_grpc
134221 def upload_file_stream (self , ** kwargs ) -> dict : # noqa: D102
0 commit comments