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 | ||||
|         # This stores "git diff" or "hg diff" into the experiment's "script.requirements.diff" section | ||||
|         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: true | ||||
|  | ||||
| @ -51,6 +51,7 @@ class Detector(object): | ||||
|     """ | ||||
| 
 | ||||
|     _fallback = '_fallback' | ||||
|     _remote = '_remote' | ||||
| 
 | ||||
|     @attr.s | ||||
|     class Commands(object): | ||||
| @ -66,6 +67,10 @@ class Detector(object): | ||||
|         # alternative commands | ||||
|         branch_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): | ||||
|         self.type_name = type_name | ||||
| @ -75,14 +80,14 @@ class Detector(object): | ||||
|         """ Returns a RepoInfo instance containing a command for each info attribute """ | ||||
|         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 """ | ||||
|         try: | ||||
|             return get_command_output(command, path, strip=strip) | ||||
| 
 | ||||
|         except (CalledProcessError, UnicodeDecodeError) as ex: | ||||
|             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: | ||||
|                     try: | ||||
|                         return get_command_output(fallback_command, path, strip=strip) | ||||
| @ -97,11 +102,12 @@ class Detector(object): | ||||
|             ) | ||||
|             return "" | ||||
| 
 | ||||
|     def _get_info(self, path, include_diff=False): | ||||
|     def _get_info(self, path, include_diff=False, diff_from_remote=False): | ||||
|         """ | ||||
|         Get repository information. | ||||
|         :param path: Path to repository | ||||
|         :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 | ||||
|         """ | ||||
|         path = str(path) | ||||
| @ -109,28 +115,56 @@ class Detector(object): | ||||
|         if not include_diff: | ||||
|             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( | ||||
|             **{ | ||||
|                 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() | ||||
|                 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 | ||||
| 
 | ||||
|     def _post_process_info(self, info): | ||||
|         # check if there are uncommitted changes in the current repository | ||||
|         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. | ||||
|         :param path: Path to repository | ||||
|         :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 | ||||
|         """ | ||||
|         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) | ||||
| 
 | ||||
|     def _is_repo_type(self, script_path): | ||||
| @ -200,6 +234,9 @@ class GitDetector(Detector): | ||||
|             modified=["git", "ls-files", "-m"], | ||||
|             branch_fallback=["git", "rev-parse", "--abbrev-ref", "HEAD"], | ||||
|             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): | ||||
| @ -234,7 +271,7 @@ class EnvDetector(Detector): | ||||
|         except Exception: | ||||
|             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() | ||||
| 
 | ||||
|         if not repository_url: | ||||
|  | ||||
| @ -589,7 +589,8 @@ class ScriptInfo(object): | ||||
|         return '' | ||||
| 
 | ||||
|     @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() | ||||
|         if jupyter_filepath: | ||||
|             scripts_path = [Path(os.path.normpath(jupyter_filepath)).absolute()] | ||||
| @ -623,7 +624,8 @@ class ScriptInfo(object): | ||||
|         else: | ||||
|             try: | ||||
|                 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(): | ||||
|                         script_dir = d | ||||
|                         script_path = scripts_path[i] | ||||
| @ -697,13 +699,14 @@ class ScriptInfo(object): | ||||
|                 script_requirements) | ||||
| 
 | ||||
|     @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: | ||||
|             if not filepaths: | ||||
|                 filepaths = [sys.argv[0], ] | ||||
|             return cls._get_script_info( | ||||
|                 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: | ||||
|             if log: | ||||
|                 log.warning("Failed auto-detecting task repository: {}".format(ex)) | ||||
|  | ||||
| @ -65,6 +65,7 @@ class Task(IdObjectBase, AccessMixin, SetupUploadMixin): | ||||
|     _force_requirements = {} | ||||
| 
 | ||||
|     _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' | ||||
| 
 | ||||
|     class TaskTypes(Enum): | ||||
| @ -276,7 +277,8 @@ class Task(IdObjectBase, AccessMixin, SetupUploadMixin): | ||||
|             result, script_requirements = ScriptInfo.get( | ||||
|                 filepaths=[self._calling_filename, sys.argv[0], ] | ||||
|                 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: | ||||
|                 self.get_logger().report_text(msg) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 allegroai
						allegroai