Copy file to default location if it does not already exist This tries to move a default configuration file to a default location if if does not already exist. It also comments out that file by default. This is to be used by downstream modules (like dask.distributed) that may
(
source: str, destination: str | None = None, comment: bool = True
)
| 307 | |
| 308 | |
| 309 | def ensure_file( |
| 310 | source: str, destination: str | None = None, comment: bool = True |
| 311 | ) -> None: |
| 312 | """ |
| 313 | Copy file to default location if it does not already exist |
| 314 | |
| 315 | This tries to move a default configuration file to a default location if |
| 316 | if does not already exist. It also comments out that file by default. |
| 317 | |
| 318 | This is to be used by downstream modules (like dask.distributed) that may |
| 319 | have default configuration files that they wish to include in the default |
| 320 | configuration path. |
| 321 | |
| 322 | Parameters |
| 323 | ---------- |
| 324 | source : string, filename |
| 325 | Source configuration file, typically within a source directory. |
| 326 | destination : string, directory |
| 327 | Destination directory. Configurable by ``DASK_CONFIG`` environment |
| 328 | variable, falling back to ~/.config/dask. |
| 329 | comment : bool, True by default |
| 330 | Whether or not to comment out the config file when copying. |
| 331 | """ |
| 332 | if destination is None: |
| 333 | destination = PATH |
| 334 | |
| 335 | # destination is a file and already exists, never overwrite |
| 336 | if os.path.isfile(destination): |
| 337 | return |
| 338 | |
| 339 | # If destination is not an existing file, interpret as a directory, |
| 340 | # use the source basename as the filename |
| 341 | directory = destination |
| 342 | destination = os.path.join(directory, os.path.basename(source)) |
| 343 | |
| 344 | try: |
| 345 | if not os.path.exists(destination): |
| 346 | os.makedirs(directory, exist_ok=True) |
| 347 | |
| 348 | # Atomically create destination. Parallel testing discovered |
| 349 | # a race condition where a process can be busy creating the |
| 350 | # destination while another process reads an empty config file. |
| 351 | tmp = f"{destination}.tmp.{os.getpid()}" |
| 352 | with open(source) as f: |
| 353 | lines = list(f) |
| 354 | |
| 355 | if comment: |
| 356 | lines = [ |
| 357 | f"# {line}" if line.strip() and not line.startswith("#") else line |
| 358 | for line in lines |
| 359 | ] |
| 360 | |
| 361 | with open(tmp, "w") as f: |
| 362 | f.write("".join(lines)) |
| 363 | |
| 364 | try: |
| 365 | os.rename(tmp, destination) |
| 366 | except OSError: |
searching dependent graphs…