@@ -111,12 +111,49 @@ def OpenVSCode(self):
111
111
# Ensure workspace file exists, create if necessary
112
112
project_folder = Path (project .folder )
113
113
workspace_path = project_folder / self .workspace
114
+
115
+ # Get the interpreter path
116
+ interpreter_path = self ._get_interpreter_path ()
117
+
118
+ # Load existing workspace config or create new one
119
+ if workspace_path .exists ():
120
+ with workspace_path .open ('r' ) as file :
121
+ workspace_config = json .load (file )
122
+ else :
123
+ workspace_config = {"folders" : [{"path" : "." }]}
124
+
125
+ # Initialize settings if it doesn't exist
126
+ if "settings" not in workspace_config :
127
+ workspace_config ["settings" ] = {}
128
+
129
+ # Update Python settings to force workspace interpreter
130
+ python_settings = {
131
+ "python.defaultInterpreterPath" : str (interpreter_path ),
132
+ "python.terminal.activateEnvironment" : True
133
+ }
134
+
135
+ # Update workspace settings
136
+ workspace_config ["settings" ].update (python_settings )
137
+
138
+ # Save the workspace config
139
+ with workspace_path .open ('w' ) as file :
140
+ json .dump (workspace_config , file , indent = 4 )
141
+
114
142
if not workspace_path .exists ():
115
- with workspace_path .open ('w' ) as file :
116
- json .dump ({"folders" : [{"path" : "." }]}, file )
117
143
self .logger .Log (f"Created workspace file: { workspace_path } " )
118
- if TDTypings := getattr (op , FNS_TDTYPINGS , None ):
144
+ else :
145
+ self .logger .Log (f"Updated interpreter path in workspace file: { workspace_path } " )
146
+
147
+ # Check if we're using a valid TD interpreter or falling back to local typings
148
+ interpreter_parent = interpreter_path .parent
149
+ version = self ._parse_td_version (interpreter_parent .parent )
150
+
151
+ # Only deploy stubs if we're not using a valid TD interpreter
152
+ if not self ._is_valid_td_version (version ):
153
+ if TDTypings := getattr (op , 'FNS_TDTYPINGS' , None ):
154
+ self .logger .Log ("Deploying stubs because no valid TD interpreter found" )
119
155
TDTypings .DeployStubs ()
156
+
120
157
missing_workspace = not self .workspace or not Path (self .workspace ).exists ()
121
158
122
159
if missing_exe or missing_workspace :
@@ -144,3 +181,77 @@ def _popErrorMessage(self, missing_exe=False, missing_workspace=False):
144
181
ui .messageBox ("Error" , message , buttons = ["OK" ])
145
182
self .ownerComp .openParameters ()
146
183
pass
184
+
185
+ def _parse_td_version (self , path : Path ) -> tuple [int , int ] | None :
186
+ """Extract TouchDesigner version from path."""
187
+ td_pattern = re .compile (r'TouchDesigner\.(\d+)\.(\d+)' )
188
+ # Check folder name for version
189
+ match = td_pattern .match (path .name )
190
+ if match :
191
+ return (int (match .group (1 )), int (match .group (2 )))
192
+ return None
193
+
194
+ def _is_valid_td_version (self , version : tuple [int , int ] | None ) -> bool :
195
+ """Check if version meets minimum requirements (>= 2023.3000)."""
196
+ if version is None :
197
+ return False
198
+ major , minor = version
199
+ if major > 2023 :
200
+ return True
201
+ elif major == 2023 :
202
+ return minor >= 30000
203
+ return False
204
+
205
+ def _find_td_interpreter (self ) -> Path | None :
206
+ """Search for valid python.exe in the highest version TD installation."""
207
+ # First check current app version
208
+ current_td = Path (app .installFolder )
209
+ version = self ._parse_td_version (current_td )
210
+ self .logger .Log (f"Current TD version: { version } " )
211
+
212
+ # Always check if current interpreter exists
213
+ td_interpreter = current_td / 'bin' / 'python.exe'
214
+ if td_interpreter .exists ():
215
+ if self ._is_valid_td_version (version ):
216
+ self .logger .Log (f"Using current TD interpreter in { version [0 ]} .{ version [1 ]} " )
217
+ return td_interpreter
218
+ else :
219
+ self .logger .Log ("Current TD version is not valid, but interpreter exists" )
220
+ # Store current interpreter as fallback
221
+ current_interpreter = td_interpreter
222
+ else :
223
+ current_interpreter = None
224
+ self .logger .Log ("Current TD interpreter not found" )
225
+
226
+ # If current version is not valid, search for highest version
227
+ td_installations = current_td .parent
228
+ highest_match = None
229
+ highest_version = (0 , 0 )
230
+
231
+ for td_folder in td_installations .iterdir ():
232
+ if not td_folder .is_dir ():
233
+ continue
234
+
235
+ version = self ._parse_td_version (td_folder )
236
+ if self ._is_valid_td_version (version ) and version > highest_version :
237
+ td_interpreter = td_folder / 'bin' / 'python.exe'
238
+ if td_interpreter .exists ():
239
+ highest_version = version
240
+ highest_match = td_interpreter
241
+ self .logger .Log (f"Found interpreter in TD { version [0 ]} .{ version [1 ]} " )
242
+
243
+ # Return highest valid version if found, otherwise return current interpreter
244
+ return highest_match if highest_match else current_interpreter
245
+
246
+ def _get_interpreter_path (self ) -> Path :
247
+ """Determine paths for builtins and stubs files."""
248
+ # Try to find builtins in highest version TD installation
249
+ td_interpreter = self ._find_td_interpreter ()
250
+ if td_interpreter :
251
+ interpreter_file = td_interpreter
252
+ else :
253
+ self .logger .Log ("No valid TD installation (>= 2023.3000) found with python.exe" )
254
+ # Fallback to local typings
255
+ interpreter_file = Path ("typings" , "python.exe" )
256
+
257
+ return interpreter_file
0 commit comments