|
5 | 5 | import sys
|
6 | 6 | import time
|
7 | 7 | from dataclasses import dataclass
|
| 8 | +from functools import partial |
8 | 9 | from pathlib import Path
|
9 | 10 | from textwrap import dedent
|
10 | 11 | from typing import Any, List, Optional, Union
|
|
62 | 63 | from lightning_app.runners.backends.cloud import CloudBackend
|
63 | 64 | from lightning_app.runners.runtime import Runtime
|
64 | 65 | from lightning_app.source_code import LocalSourceCodeDir
|
| 66 | +from lightning_app.source_code.copytree import _filter_ignored, _parse_lightningignore |
65 | 67 | from lightning_app.storage import Drive, Mount
|
66 | 68 | from lightning_app.utilities.app_helpers import _is_headless, Logger
|
67 | 69 | from lightning_app.utilities.cloud import _get_project
|
@@ -217,7 +219,19 @@ def dispatch(
|
217 | 219 | root = Path(self.entrypoint_file).absolute().parent
|
218 | 220 | cleanup_handle = _prepare_lightning_wheels_and_requirements(root)
|
219 | 221 | self.app._update_index_file()
|
220 |
| - repo = LocalSourceCodeDir(path=root) |
| 222 | + |
| 223 | + # gather and merge all lightningignores |
| 224 | + children = self.app.flows + self.app.works |
| 225 | + lightningignores = [c.lightningignore for c in children] |
| 226 | + if lightningignores: |
| 227 | + merged = sum(lightningignores, tuple()) |
| 228 | + logger.debug(f"Found the following lightningignores: {merged}") |
| 229 | + patterns = _parse_lightningignore(merged) |
| 230 | + ignore_functions = [partial(_filter_ignored, root, patterns)] |
| 231 | + else: |
| 232 | + ignore_functions = None |
| 233 | + |
| 234 | + repo = LocalSourceCodeDir(path=root, ignore_functions=ignore_functions) |
221 | 235 | self._check_uploaded_folder(root, repo)
|
222 | 236 | requirements_file = root / "requirements.txt"
|
223 | 237 | # The entry point file needs to be relative to the root of the uploaded source file directory,
|
@@ -493,24 +507,34 @@ def _ensure_cluster_project_binding(self, project_id: str, cluster_id: str):
|
493 | 507 | @staticmethod
|
494 | 508 | def _check_uploaded_folder(root: Path, repo: LocalSourceCodeDir) -> None:
|
495 | 509 | """This method is used to inform the users if their folder files are large and how to filter them."""
|
496 |
| - lightning_tar = set(fnmatch.filter(repo.files, "*lightning-*.tar.gz")) |
497 |
| - app_folder_size = sum(Path(p).stat().st_size for p in repo.files if p not in lightning_tar) |
498 |
| - app_folder_size_in_mb = round(app_folder_size / (1000 * 1000), 5) |
| 510 | + excludes = set(fnmatch.filter(repo.files, "*lightning-*.tar.gz")) |
| 511 | + excludes.update(fnmatch.filter(repo.files, ".lightningignore")) |
| 512 | + files = [Path(f) for f in repo.files if f not in excludes] |
| 513 | + file_sizes = {f: f.stat().st_size for f in files} |
| 514 | + mb = 1000_000 |
| 515 | + app_folder_size_in_mb = sum(file_sizes.values()) / mb |
499 | 516 | if app_folder_size_in_mb > CLOUD_UPLOAD_WARNING:
|
500 |
| - path_sizes = [(p, Path(p).stat().st_size / (1000 * 1000)) for p in repo.files] |
501 |
| - largest_paths = sorted((x for x in path_sizes if x[-1] > 0.01), key=lambda x: x[1], reverse=True)[:25] |
502 |
| - largest_paths_msg = "\n".join(f"{round(s, 5)} MB: {p}" for p, s in largest_paths) |
| 517 | + # filter out files under 0.01mb |
| 518 | + relevant_files = {f: sz for f, sz in file_sizes.items() if sz > 0.01 * mb} |
| 519 | + if relevant_files: |
| 520 | + by_largest = dict(sorted(relevant_files.items(), key=lambda x: x[1], reverse=True)) |
| 521 | + by_largest = dict(list(by_largest.items())[:25]) # trim |
| 522 | + largest_paths_msg = "\n".join( |
| 523 | + f"{round(sz / mb, 5)} MB: {p.relative_to(root)}" for p, sz in by_largest.items() |
| 524 | + ) |
| 525 | + largest_paths_msg = f"Here are the largest files:\n{largest_paths_msg}\n" |
| 526 | + else: |
| 527 | + largest_paths_msg = "" |
503 | 528 | warning_msg = (
|
504 | 529 | f"Your application folder '{root.absolute()}' is more than {CLOUD_UPLOAD_WARNING} MB. "
|
505 |
| - f"The total size is {app_folder_size_in_mb} MB\n" |
506 |
| - f"Here are the largest files: \n{largest_paths_msg}\n" |
507 |
| - "Perhaps you should try running the app in an empty directory." |
| 530 | + f"The total size is {round(app_folder_size_in_mb, 2)} MB. {len(files)} files were uploaded.\n" |
| 531 | + + largest_paths_msg |
| 532 | + + "Perhaps you should try running the app in an empty directory." |
508 | 533 | )
|
509 | 534 | if not (root / DOT_IGNORE_FILENAME).is_file():
|
510 |
| - warning_msg = ( |
511 |
| - warning_msg |
512 |
| - + "\nIn order to ignore some files or folder, " |
513 |
| - + "create a `.lightningignore` file and add the paths to ignore." |
| 535 | + warning_msg += ( |
| 536 | + "\nIn order to ignore some files or folder, create a `.lightningignore` file and add the paths to" |
| 537 | + " ignore. You can also set the `lightningingore` attribute in a Flow or Work." |
514 | 538 | )
|
515 | 539 | else:
|
516 | 540 | warning_msg += "\nYou can ignore some files or folders by adding them to `.lightningignore`."
|
|
0 commit comments