@@ -91,6 +91,39 @@ def before_is_valid(self, line: str) -> None:
9191 self .cfg_file .write (line )
9292
9393
94+ class SafeRClone (rclone .RClone ):
95+ """
96+ A subclass of rclone.RClone that uses delete=False for the temporary
97+ config file. This prevents file locking issues on Windows where the file
98+ cannot be opened by the subprocess while it is still open in Python.
99+ """
100+ def run_cmd (self , command , extra_args = None ):
101+ if extra_args is None :
102+ extra_args = []
103+
104+ # Create a named temporary file, but don't delete it automatically
105+ # on close, so we can close it before passing to rclone.
106+ with tempfile .NamedTemporaryFile (mode = 'wt' , delete = False ) as cfg_file :
107+ cfg_file_path = cfg_file .name
108+ try :
109+ self .log .debug ("rclone config: ~%s~" , self .cfg )
110+ cfg_file .write (self .cfg )
111+ cfg_file .flush ()
112+ # Close the file so other processes can access it (Windows fix)
113+ cfg_file .close ()
114+
115+ command_with_args = [
116+ "rclone" , command , "--config" , cfg_file_path
117+ ]
118+ command_with_args += extra_args
119+ command_result = self ._execute (command_with_args )
120+ return command_result
121+ finally :
122+ # Manually clean up the file
123+ if os .path .exists (cfg_file_path ):
124+ os .remove (cfg_file_path )
125+
126+
94127def get_rclone_instance (
95128 config : str , files : str , remote_folder_name : str
96129) -> rclone .RClone :
@@ -151,7 +184,8 @@ def get_rclone_instance(
151184
152185 # Get the content
153186 o = tmp_config_file .getvalue ()
154- rclone_instance = rclone .with_config (o )
187+ # Use our SafeRClone instead of rclone.with_config
188+ rclone_instance = SafeRClone (cfg = o )
155189
156190 # I think that given a file, any file, rclone.with_config() will always
157191 # return _something_ as it doesn't validate the config file
0 commit comments