mirror of
				https://github.com/clearml/clearml
				synced 2025-06-26 18:16:07 +00:00 
			
		
		
		
	Add sdk.development.store_code_diff_from_remote (default False) to store diff from remote HEAD instead of local HEAD (issue #222)
This commit is contained in:
		
							parent
							
								
									a0ec4b895b
								
							
						
					
					
						commit
						753b3ff68c
					
				| @ -147,6 +147,7 @@ sdk { | |||||||
|         # Store uncommitted git/hg source code diff in experiment manifest when training in development mode |         # Store uncommitted git/hg source code diff in experiment manifest when training in development mode | ||||||
|         # This stores "git diff" or "hg diff" into the experiment's "script.requirements.diff" section |         # This stores "git diff" or "hg diff" into the experiment's "script.requirements.diff" section | ||||||
|         store_uncommitted_code_diff: true |         store_uncommitted_code_diff: true | ||||||
|  |         store_code_diff_from_remote: false | ||||||
| 
 | 
 | ||||||
|         # Support stopping an experiment in case it was externally stopped, status was changed or task was reset |         # Support stopping an experiment in case it was externally stopped, status was changed or task was reset | ||||||
|         support_stopping: true |         support_stopping: true | ||||||
|  | |||||||
| @ -51,6 +51,7 @@ class Detector(object): | |||||||
|     """ |     """ | ||||||
| 
 | 
 | ||||||
|     _fallback = '_fallback' |     _fallback = '_fallback' | ||||||
|  |     _remote = '_remote' | ||||||
| 
 | 
 | ||||||
|     @attr.s |     @attr.s | ||||||
|     class Commands(object): |     class Commands(object): | ||||||
| @ -66,6 +67,10 @@ class Detector(object): | |||||||
|         # alternative commands |         # alternative commands | ||||||
|         branch_fallback = attr.ib(default=None, type=list) |         branch_fallback = attr.ib(default=None, type=list) | ||||||
|         diff_fallback = attr.ib(default=None, type=list) |         diff_fallback = attr.ib(default=None, type=list) | ||||||
|  |         # remote commands | ||||||
|  |         commit_remote = attr.ib(default=None, type=list) | ||||||
|  |         diff_remote = attr.ib(default=None, type=list) | ||||||
|  |         diff_fallback_remote = attr.ib(default=None, type=list) | ||||||
| 
 | 
 | ||||||
|     def __init__(self, type_name, name=None): |     def __init__(self, type_name, name=None): | ||||||
|         self.type_name = type_name |         self.type_name = type_name | ||||||
| @ -75,14 +80,14 @@ class Detector(object): | |||||||
|         """ Returns a RepoInfo instance containing a command for each info attribute """ |         """ Returns a RepoInfo instance containing a command for each info attribute """ | ||||||
|         return self.Commands() |         return self.Commands() | ||||||
| 
 | 
 | ||||||
|     def _get_command_output(self, path, name, command, strip=True): |     def _get_command_output(self, path, name, command, commands=None, strip=True): | ||||||
|         """ Run a command and return its output """ |         """ Run a command and return its output """ | ||||||
|         try: |         try: | ||||||
|             return get_command_output(command, path, strip=strip) |             return get_command_output(command, path, strip=strip) | ||||||
| 
 | 
 | ||||||
|         except (CalledProcessError, UnicodeDecodeError) as ex: |         except (CalledProcessError, UnicodeDecodeError) as ex: | ||||||
|             if not name.endswith(self._fallback): |             if not name.endswith(self._fallback): | ||||||
|                 fallback_command = attr.asdict(self._get_commands()).get(name + self._fallback) |                 fallback_command = attr.asdict(commands or self._get_commands()).get(name + self._fallback) | ||||||
|                 if fallback_command: |                 if fallback_command: | ||||||
|                     try: |                     try: | ||||||
|                         return get_command_output(fallback_command, path, strip=strip) |                         return get_command_output(fallback_command, path, strip=strip) | ||||||
| @ -97,11 +102,12 @@ class Detector(object): | |||||||
|             ) |             ) | ||||||
|             return "" |             return "" | ||||||
| 
 | 
 | ||||||
|     def _get_info(self, path, include_diff=False): |     def _get_info(self, path, include_diff=False, diff_from_remote=False): | ||||||
|         """ |         """ | ||||||
|         Get repository information. |         Get repository information. | ||||||
|         :param path: Path to repository |         :param path: Path to repository | ||||||
|         :param include_diff: Whether to include the diff command's output (if available) |         :param include_diff: Whether to include the diff command's output (if available) | ||||||
|  |         :param diff_from_remote: Whether to store the remote diff/commit based on the remote commit (not local commit) | ||||||
|         :return: RepoInfo instance |         :return: RepoInfo instance | ||||||
|         """ |         """ | ||||||
|         path = str(path) |         path = str(path) | ||||||
| @ -109,28 +115,56 @@ class Detector(object): | |||||||
|         if not include_diff: |         if not include_diff: | ||||||
|             commands.diff = None |             commands.diff = None | ||||||
| 
 | 
 | ||||||
|  |         # skip the local commands | ||||||
|  |         if diff_from_remote and commands: | ||||||
|  |             for name, command in attr.asdict(commands).items(): | ||||||
|  |                 if name.endswith(self._remote) and command: | ||||||
|  |                     setattr(commands, name[:-len(self._remote)], None) | ||||||
|  | 
 | ||||||
|         info = Result( |         info = Result( | ||||||
|             **{ |             **{ | ||||||
|                 name: self._get_command_output(path, name, command, strip=bool(name != 'diff')) |                 name: self._get_command_output(path, name, command, commands=commands, strip=bool(name != 'diff')) | ||||||
|                 for name, command in attr.asdict(commands).items() |                 for name, command in attr.asdict(commands).items() | ||||||
|                 if command and not name.endswith(self._fallback) |                 if command and not name.endswith(self._fallback) and not name.endswith(self._remote) | ||||||
|             } |             } | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|  |         if diff_from_remote and commands: | ||||||
|  |             for name, command in attr.asdict(commands).items(): | ||||||
|  |                 if name.endswith(self._remote) and command: | ||||||
|  |                     setattr(commands, name[:-len(self._remote)], command+[info.branch]) | ||||||
|  | 
 | ||||||
|  |             info = attr.assoc( | ||||||
|  |                 info, | ||||||
|  |                 **{ | ||||||
|  |                     name[:-len(self._remote)]: self._get_command_output( | ||||||
|  |                         path, name[:-len(self._remote)], command + [info.branch], | ||||||
|  |                         commands=commands, strip=name.startswith('diff')) | ||||||
|  |                     for name, command in attr.asdict(commands).items() | ||||||
|  |                     if command and ( | ||||||
|  |                             name.endswith(self._remote) and | ||||||
|  |                             not name[:-len(self._remote)].endswith(self._fallback) | ||||||
|  |                     ) | ||||||
|  |                 } | ||||||
|  |             ) | ||||||
|  |             # make sure we match the modified with the git remote diff state | ||||||
|  |             info.modified = bool(info.diff) | ||||||
|  | 
 | ||||||
|         return info |         return info | ||||||
| 
 | 
 | ||||||
|     def _post_process_info(self, info): |     def _post_process_info(self, info): | ||||||
|         # check if there are uncommitted changes in the current repository |         # check if there are uncommitted changes in the current repository | ||||||
|         return info |         return info | ||||||
| 
 | 
 | ||||||
|     def get_info(self, path, include_diff=False): |     def get_info(self, path, include_diff=False, diff_from_remote=False): | ||||||
|         """ |         """ | ||||||
|         Get repository information. |         Get repository information. | ||||||
|         :param path: Path to repository |         :param path: Path to repository | ||||||
|         :param include_diff: Whether to include the diff command's output (if available) |         :param include_diff: Whether to include the diff command's output (if available) | ||||||
|  |         :param diff_from_remote: Whether to store the remote diff/commit based on the remote commit (not local commit) | ||||||
|         :return: RepoInfo instance |         :return: RepoInfo instance | ||||||
|         """ |         """ | ||||||
|         info = self._get_info(path, include_diff) |         info = self._get_info(path, include_diff, diff_from_remote=diff_from_remote) | ||||||
|         return self._post_process_info(info) |         return self._post_process_info(info) | ||||||
| 
 | 
 | ||||||
|     def _is_repo_type(self, script_path): |     def _is_repo_type(self, script_path): | ||||||
| @ -200,6 +234,9 @@ class GitDetector(Detector): | |||||||
|             modified=["git", "ls-files", "-m"], |             modified=["git", "ls-files", "-m"], | ||||||
|             branch_fallback=["git", "rev-parse", "--abbrev-ref", "HEAD"], |             branch_fallback=["git", "rev-parse", "--abbrev-ref", "HEAD"], | ||||||
|             diff_fallback=["git", "diff"], |             diff_fallback=["git", "diff"], | ||||||
|  |             diff_remote=["git", "diff", "--submodule=diff", ], | ||||||
|  |             commit_remote=["git", "rev-parse", ], | ||||||
|  |             diff_fallback_remote=["git", "diff", ], | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|     def _post_process_info(self, info): |     def _post_process_info(self, info): | ||||||
| @ -234,7 +271,7 @@ class EnvDetector(Detector): | |||||||
|         except Exception: |         except Exception: | ||||||
|             return Path.cwd() |             return Path.cwd() | ||||||
| 
 | 
 | ||||||
|     def _get_info(self, _, include_diff=False): |     def _get_info(self, _, include_diff=False, diff_from_remote=None): | ||||||
|         repository_url = VCS_REPOSITORY_URL.get() |         repository_url = VCS_REPOSITORY_URL.get() | ||||||
| 
 | 
 | ||||||
|         if not repository_url: |         if not repository_url: | ||||||
|  | |||||||
| @ -589,7 +589,8 @@ class ScriptInfo(object): | |||||||
|         return '' |         return '' | ||||||
| 
 | 
 | ||||||
|     @classmethod |     @classmethod | ||||||
|     def _get_script_info(cls, filepaths, check_uncommitted=True, create_requirements=True, log=None): |     def _get_script_info(cls, filepaths, check_uncommitted=True, create_requirements=True, log=None, | ||||||
|  |                          uncommitted_from_remote=False): | ||||||
|         jupyter_filepath = cls._get_jupyter_notebook_filename() |         jupyter_filepath = cls._get_jupyter_notebook_filename() | ||||||
|         if jupyter_filepath: |         if jupyter_filepath: | ||||||
|             scripts_path = [Path(os.path.normpath(jupyter_filepath)).absolute()] |             scripts_path = [Path(os.path.normpath(jupyter_filepath)).absolute()] | ||||||
| @ -623,7 +624,8 @@ class ScriptInfo(object): | |||||||
|         else: |         else: | ||||||
|             try: |             try: | ||||||
|                 for i, d in enumerate(scripts_dir): |                 for i, d in enumerate(scripts_dir): | ||||||
|                     repo_info = plugin.get_info(str(d), include_diff=check_uncommitted) |                     repo_info = plugin.get_info( | ||||||
|  |                         str(d), include_diff=check_uncommitted, diff_from_remote=uncommitted_from_remote) | ||||||
|                     if not repo_info.is_empty(): |                     if not repo_info.is_empty(): | ||||||
|                         script_dir = d |                         script_dir = d | ||||||
|                         script_path = scripts_path[i] |                         script_path = scripts_path[i] | ||||||
| @ -697,13 +699,14 @@ class ScriptInfo(object): | |||||||
|                 script_requirements) |                 script_requirements) | ||||||
| 
 | 
 | ||||||
|     @classmethod |     @classmethod | ||||||
|     def get(cls, filepaths=None, check_uncommitted=True, create_requirements=True, log=None): |     def get(cls, filepaths=None, check_uncommitted=True, create_requirements=True, log=None, | ||||||
|  |             uncommitted_from_remote=False): | ||||||
|         try: |         try: | ||||||
|             if not filepaths: |             if not filepaths: | ||||||
|                 filepaths = [sys.argv[0], ] |                 filepaths = [sys.argv[0], ] | ||||||
|             return cls._get_script_info( |             return cls._get_script_info( | ||||||
|                 filepaths=filepaths, check_uncommitted=check_uncommitted, |                 filepaths=filepaths, check_uncommitted=check_uncommitted, | ||||||
|                 create_requirements=create_requirements, log=log) |                 create_requirements=create_requirements, log=log, uncommitted_from_remote=uncommitted_from_remote) | ||||||
|         except Exception as ex: |         except Exception as ex: | ||||||
|             if log: |             if log: | ||||||
|                 log.warning("Failed auto-detecting task repository: {}".format(ex)) |                 log.warning("Failed auto-detecting task repository: {}".format(ex)) | ||||||
|  | |||||||
| @ -65,6 +65,7 @@ class Task(IdObjectBase, AccessMixin, SetupUploadMixin): | |||||||
|     _force_requirements = {} |     _force_requirements = {} | ||||||
| 
 | 
 | ||||||
|     _store_diff = config.get('development.store_uncommitted_code_diff', False) |     _store_diff = config.get('development.store_uncommitted_code_diff', False) | ||||||
|  |     _store_remote_diff = config.get('development.store_code_diff_from_remote', False) | ||||||
|     _offline_filename = 'task.json' |     _offline_filename = 'task.json' | ||||||
| 
 | 
 | ||||||
|     class TaskTypes(Enum): |     class TaskTypes(Enum): | ||||||
| @ -276,7 +277,8 @@ class Task(IdObjectBase, AccessMixin, SetupUploadMixin): | |||||||
|             result, script_requirements = ScriptInfo.get( |             result, script_requirements = ScriptInfo.get( | ||||||
|                 filepaths=[self._calling_filename, sys.argv[0], ] |                 filepaths=[self._calling_filename, sys.argv[0], ] | ||||||
|                 if ScriptInfo.is_running_from_module() else [sys.argv[0], self._calling_filename, ], |                 if ScriptInfo.is_running_from_module() else [sys.argv[0], self._calling_filename, ], | ||||||
|                 log=self.log, create_requirements=False, check_uncommitted=self._store_diff |                 log=self.log, create_requirements=False, | ||||||
|  |                 check_uncommitted=self._store_diff, uncommitted_from_remote=self._store_remote_diff | ||||||
|             ) |             ) | ||||||
|             for msg in result.warning_messages: |             for msg in result.warning_messages: | ||||||
|                 self.get_logger().report_text(msg) |                 self.get_logger().report_text(msg) | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 allegroai
						allegroai