From aea342e31023d339e32c89b50d383f0e4faf7e5b Mon Sep 17 00:00:00 2001 From: Grigori Fursin Date: Fri, 18 Oct 2024 18:04:32 +0200 Subject: [PATCH 1/5] Added self-time: https://github.com/mlcommons/ck/issues/1332 (cmx -time) --- cm/cmind/__init__.py | 2 +- cm/cmind/core.py | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/cm/cmind/__init__.py b/cm/cmind/__init__.py index 8319cb86c..a99021d8c 100644 --- a/cm/cmind/__init__.py +++ b/cm/cmind/__init__.py @@ -2,7 +2,7 @@ # # Written by Grigori Fursin -__version__ = "3.2.4" +__version__ = "3.2.4.1" from cmind.core import access from cmind.core import x diff --git a/cm/cmind/core.py b/cm/cmind/core.py index f563fbfa1..85e18e39f 100644 --- a/cm/cmind/core.py +++ b/cm/cmind/core.py @@ -842,7 +842,7 @@ def x(self, i, out = None): 'h', 'help', 'version', 'out', 'j', 'json', 'save_to_json_file', 'save_to_yaml_file', 'common', 'ignore_inheritance', 'log', 'logfile', 'raise', 'repro', - 'f']] + 'f', 'time']] if len(unknown_control_flags)>0: unknown_control_flags_str = ','.join(unknown_control_flags) @@ -855,6 +855,11 @@ def x(self, i, out = None): if control.pop('f', ''): i['f'] = True + self_time = control.pop('time', False) + if not x_was_called and self_time: + import time + self_time1 = time.time() + # Check repro use_log = str(control_flags.pop('log', '')).strip().lower() log_file = control_flags.pop('logfile', '') @@ -939,6 +944,14 @@ def x(self, i, out = None): # Very first call (not recursive) # Check if output to json and save file + if self_time: + self_time = time.time() - self_time1 + r['self_time'] = self_time + + if self.output == 'con': + print ('') + print ('CMX elapsed time: {:.3f} sec.'.format(self_time)) + if self.output == 'json': utils.dump_safe_json(r) @@ -1211,7 +1224,7 @@ def _x(self, i, control): return {'return':4, 'error':'automation meta not found in {}'.format(automation_path)} # Load artifact class - r=utils.load_yaml_and_json(automation_path_meta) + r = utils.load_yaml_and_json(automation_path_meta) if r['return']>0: return r automation_meta = r['meta'] From 93c2eab854ac7adccf17032e02a25953c0baad16 Mon Sep 17 00:00:00 2001 From: Grigori Fursin Date: Fri, 18 Oct 2024 18:18:43 +0200 Subject: [PATCH 2/5] Added self-profile (-profile): https://github.com/mlcommons/ck/issues/1331 --- cm/cmind/core.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/cm/cmind/core.py b/cm/cmind/core.py index 85e18e39f..69411b639 100644 --- a/cm/cmind/core.py +++ b/cm/cmind/core.py @@ -842,7 +842,7 @@ def x(self, i, out = None): 'h', 'help', 'version', 'out', 'j', 'json', 'save_to_json_file', 'save_to_yaml_file', 'common', 'ignore_inheritance', 'log', 'logfile', 'raise', 'repro', - 'f', 'time']] + 'f', 'time', 'profile']] if len(unknown_control_flags)>0: unknown_control_flags_str = ','.join(unknown_control_flags) @@ -855,11 +855,13 @@ def x(self, i, out = None): if control.pop('f', ''): i['f'] = True - self_time = control.pop('time', False) + self_time = control.get('time', False) if not x_was_called and self_time: import time self_time1 = time.time() + self_profile = control.get('profile', False) + # Check repro use_log = str(control_flags.pop('log', '')).strip().lower() log_file = control_flags.pop('logfile', '') @@ -933,6 +935,13 @@ def x(self, i, out = None): self.log(f"x input: {spaces} ({i})", "debug") # Call access helper + if not x_was_called and self_profile: + # https://docs.python.org/3/library/profile.html#module-cProfile + import cProfile, pstats, io + from pstats import SortKey + profile = cProfile.Profile() + profile.enable() + r = self._x(i, control) if not self.logger == None: @@ -941,6 +950,17 @@ def x(self, i, out = None): self.state['recursion'] = recursion if not x_was_called: + if self_profile: + profile.disable() + s = io.StringIO() + sortby = SortKey.CUMULATIVE + ps = pstats.Stats(profile, stream=s).sort_stats(sortby) + ps.print_stats(32) + print ('') + print ('CMX profile:') + print ('') + print (s.getvalue()) + # Very first call (not recursive) # Check if output to json and save file From 100bc66230e02bb03883c7ec77286f4516b1e3c6 Mon Sep 17 00:00:00 2001 From: Grigori Fursin Date: Fri, 18 Oct 2024 18:19:36 +0200 Subject: [PATCH 3/5] improve help --- cm/cmind/core.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cm/cmind/core.py b/cm/cmind/core.py index 69411b639..14ffdce1f 100644 --- a/cm/cmind/core.py +++ b/cm/cmind/core.py @@ -1071,6 +1071,8 @@ def _x(self, i, control): print (' -log={info (default) | debug | warning | error} - log level') print (' -logfile={path to log file} - record log to file instead of console') print (' -raise - raise Python error when automation action fails') + print (' -time - print elapsed time for a given automation') + print (' -profile - profile a given automation') print (' -repro - record various info to the cmx-repro directory to replay CMX command') print ('') print ('Check https://github.com/mlcommons/ck/tree/master/cm/docs/cmx for more details.') From bc800cfb92716677a6a1ab118c6b0e1c7c4996be Mon Sep 17 00:00:00 2001 From: Grigori Fursin Date: Sat, 19 Oct 2024 15:04:01 +0200 Subject: [PATCH 4/5] Fixed bug when detecting unknown control flag: https://github.com/mlcommons/ck/issues/1333 --- cm/CHANGES.md | 1 + cm/cmind/core.py | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/cm/CHANGES.md b/cm/CHANGES.md index cd843fef2..125eb93cb 100644 --- a/cm/CHANGES.md +++ b/cm/CHANGES.md @@ -1,6 +1,7 @@ ## V3.2.4 - CMX: improved logging - CMX: improved error handling (show module path and line number) + - CMX: fixed bug when detecting unknown control flag ## V3.2.3 - added --new_branch to `cm pull repo` and `cm checkout repo` diff --git a/cm/cmind/core.py b/cm/cmind/core.py index 14ffdce1f..8ecca0566 100644 --- a/cm/cmind/core.py +++ b/cm/cmind/core.py @@ -844,11 +844,13 @@ def x(self, i, out = None): 'ignore_inheritance', 'log', 'logfile', 'raise', 'repro', 'f', 'time', 'profile']] + delayed_error = '' + if len(unknown_control_flags)>0: unknown_control_flags_str = ','.join(unknown_control_flags) - print (f'Unknown control flag(s): {unknown_control_flags_str}') - print ('') + delayed_error = f'Unknown control flag(s): {unknown_control_flags_str}' + # Force print help control['h'] = True @@ -943,7 +945,11 @@ def x(self, i, out = None): profile.enable() r = self._x(i, control) - + + if delayed_error != '' and r['return'] == 0: + r['return'] = 1 + r['error'] = delayed_error + if not self.logger == None: self.log(f"x output: {r}", "debug") From ce4738a1be0d86964ce8f7aec46617c1a1e08244 Mon Sep 17 00:00:00 2001 From: Grigori Fursin Date: Sat, 19 Oct 2024 18:50:47 +0200 Subject: [PATCH 5/5] V3.2.5 - CMX: improved logging - CMX: improved error handling (show module path and line number) - CMX: fixed bug when detecting unknown control flag - CMX: do not change output to json if -j or --json just print json in the end ... --- cm/CHANGES.md | 4 +++- cm/cmind/__init__.py | 2 +- cm/cmind/core.py | 26 ++++++++++++++++++++------ 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/cm/CHANGES.md b/cm/CHANGES.md index 125eb93cb..57b892232 100644 --- a/cm/CHANGES.md +++ b/cm/CHANGES.md @@ -1,7 +1,9 @@ -## V3.2.4 +## V3.2.5 - CMX: improved logging - CMX: improved error handling (show module path and line number) - CMX: fixed bug when detecting unknown control flag + - CMX: do not change output to json if -j or --json + just print json in the end ... ## V3.2.3 - added --new_branch to `cm pull repo` and `cm checkout repo` diff --git a/cm/cmind/__init__.py b/cm/cmind/__init__.py index a99021d8c..f7f78e1f5 100644 --- a/cm/cmind/__init__.py +++ b/cm/cmind/__init__.py @@ -2,7 +2,7 @@ # # Written by Grigori Fursin -__version__ = "3.2.4.1" +__version__ = "3.2.5" from cmind.core import access from cmind.core import x diff --git a/cm/cmind/core.py b/cm/cmind/core.py index 8ecca0566..8e3577ce1 100644 --- a/cm/cmind/core.py +++ b/cm/cmind/core.py @@ -616,7 +616,7 @@ def access(self, i, out = None): if automation=='': return {'return':4, 'error':'automation was not specified'} else: - return {'return':4, 'error':'automation {} not found'.format(automation)} + return {'return':4, 'error':'automation "{}" not found'.format(automation)} # If no automation was found or we force common automation if use_common_automation or len(automation_lst)==0: @@ -857,6 +857,8 @@ def x(self, i, out = None): if control.pop('f', ''): i['f'] = True + output_json = (control.get('j', False) or control.get('json', False)) + self_time = control.get('time', False) if not x_was_called and self_time: import time @@ -978,7 +980,7 @@ def x(self, i, out = None): print ('') print ('CMX elapsed time: {:.3f} sec.'.format(self_time)) - if self.output == 'json': + if output_json: utils.dump_safe_json(r) # Restore directory of call @@ -1014,9 +1016,10 @@ def _x(self, i, control): if output == True: output = 'con' - # Check and force json console output - if control.get('j', False) or control.get('json', False): - output = 'json' +# Changed in v3.2.5 +# # Check and force json console output +# if control.get('j', False) or control.get('json', False): +# output = 'json' # Set self.output to the output of the very first access # to print error in the end if needed @@ -1050,6 +1053,17 @@ def _x(self, i, control): elif action == 'init' and automation == '': automation = 'core' + # Can add popular shortcuts + elif action == 'ff': + task = '' + if automation != '' and (' ' in automation or ',' in automation): + task = automation + if ' ' in automation: task = automation.replace(' ',',') + i['task'] = task + automation = 'flex.flow' + action = 'run' + i['automation'] = automation + i['action'] = action # Print basic help if action == '' extra_help = True if action == 'help' and automation == '' else False @@ -1291,7 +1305,7 @@ def _x(self, i, control): if automation=='': return {'return':4, 'error':'automation was not specified'} else: - return {'return':4, 'error':f'automation {automation} not found'} + return {'return':4, 'error':f'automation "{automation}" not found'} # If no automation was found or we force common automation loaded_common_automation = False