diff --git a/python/ccdb/cmd/commands/cat.py b/python/ccdb/cmd/commands/cat.py index 4f6f093..5b9c531 100644 --- a/python/ccdb/cmd/commands/cat.py +++ b/python/ccdb/cmd/commands/cat.py @@ -5,9 +5,8 @@ from ccdb import TypeTable, Assignment from ccdb import AlchemyProvider from ccdb.cmd import CliCommandBase, UtilityArgumentParser -from ccdb.path_utils import ParseRequestResult, parse_request -from ccdb import BraceMessage as Lfm # lfm is aka log format message. See BraceMessage desc about -from sqlalchemy.orm.exc import NoResultFound +from ccdb.path_utils import ParseRequestResult, parse_request, parse_time +from ccdb import BraceMessage as Lfm # lfm is aka log format message. See BraceMessage desc about log = logging.getLogger("ccdb.cmd.commands.cat") @@ -33,13 +32,6 @@ class Cat(CliCommandBase): def __init__(self, context): CliCommandBase.__init__(self, context) - self.raw_entry = "/" # object path with possible pattern, like /mole/* - self.path = "/" # parent path - self.raw_table_path = "" - self.ass_id = 0 - self.print_horizontal = True - - self.request = ParseRequestResult() # ---------------------------------------- # process @@ -59,7 +51,7 @@ def execute(self, args): parsed_args = self.process_arguments(args) - if self.ass_id: + if parsed_args.ass_id: assignment = self.get_assignment_by_id(parsed_args.ass_id) else: assignment = self.get_assignment_by_request(parsed_args.request) @@ -123,7 +115,7 @@ def get_assignment_by_request(self, request): # ---------------------------------------- def process_arguments(self, args): parser = UtilityArgumentParser(add_help=False) - parser.add_argument("obj_name", default="") + parser.add_argument("obj_name", default="", nargs='?') # border group = parser.add_mutually_exclusive_group() @@ -140,44 +132,49 @@ def process_arguments(self, args): group.add_argument("-c", "--comments", action="store_true", dest='show_comments', default=False) group.add_argument("-nc", "--no-comments", action="store_false", dest='show_comments') - # time - group = parser.add_mutually_exclusive_group() - group.add_argument("-t", "--time", action="store_true", dest='show_date', default=False) - group.add_argument("-nt", "--no-time", action="store_true", dest='show_date') + # horizontal or vertical + parser.add_argument("-ph", "--horizontal", action="store_true", dest='user_request_print_horizontal') + parser.add_argument("-pv", "--vertical", action="store_true", dest='user_request_print_vertical') - parser.add_argument("-d", "--directory") + # Assignment parameters parser.add_argument("-v", "--variation") - parser.add_argument("-a", "--id") + parser.add_argument("-a", "--id", dest='ass_id') parser.add_argument("-r", "--run") - parser.add_argument("-f", "--file") - parser.add_argument("-ph", "--horizontal", action="store_true", dest='user_request_print_horizontal') - parser.add_argument("-pv", "--vertical", action="store_true", dest='user_request_print_vertical') + parser.add_argument("-t", "--time", required=False) + # Parse args result = parser.parse_args(args) - # parse loop - if result.obj_name: - # it probably must be a request or just a table name - result.request = parse_request(result.obj_name) + + # Parse ccdb request + result.request = parse_request(result.obj_name) if result.obj_name else ParseRequestResult() + + # Check if user set the variation + if not result.request.variation_is_parsed and result.variation: + result.request.variation = result.variation + result.request.variation_is_parsed = True # Check if user set the default variation if not result.request.variation_is_parsed and self.context.current_variation: result.request.variation = self.context.current_variation result.request.variation_is_parsed = True + # Check if user set the run + if not result.request.run_is_parsed and result.run: + result.request.run = int(result.run) + result.request.run_is_parsed = True + # Check if user set the default run if not result.request.run_is_parsed and self.context.current_run: result.request.run = self.context.current_run result.request.run_is_parsed = True - return result + # Check if user set time + if not result.request.time_is_parsed and result.time: + result.request.time_str = result.time + result.request.time = parse_time(result.time) + result.request.time_is_parsed = True - # ---------------------------------------- - # validate - # ---------------------------------------- - def validate(self): - if not self.raw_table_path: - return False - return True + return result # -------------------------------------------------------------------------------- # print_assignment_vertical @@ -209,14 +206,14 @@ def print_assignment_horizontal(self, assignment, print_header=True, display_bor # PRINT COMMENTS if comments: - # this lsep hack is for Windows. Where os.linesep is \r\n, but file might have \n only line seps + # this line sep hack is for Windows. Where os.linesep is \r\n, but file might have \n only line seps comment_str = assignment.comment if os.name == 'nt': # we make sure that it is always os.linesep on windows comment_str = comment_str.replace('\r\n', '\n').replace('\n', os.linesep) sharped_lines = "#" + str(comment_str).replace(os.linesep, os.linesep + "#") - print (sharped_lines) + print(sharped_lines) column_names = [column.name for column in table.columns] column_types = [column.type for column in table.columns] diff --git a/python/ccdb/cmd/commands/dump.py b/python/ccdb/cmd/commands/dump.py index 7022983..e36412a 100644 --- a/python/ccdb/cmd/commands/dump.py +++ b/python/ccdb/cmd/commands/dump.py @@ -29,7 +29,7 @@ def execute(self, args): self.theme = NoColorTheme() # self.context.utils["cat"].theme = NoColorTheme() - return "cat --no-borders --no-header --comments --time --horizontal " + " ".join(args) + return "cat --no-borders --no-header --comments --horizontal " + " ".join(args) def print_help(self): """Prints help of the command""" diff --git a/python/ccdb/path_utils.py b/python/ccdb/path_utils.py index e927917..da5ae92 100644 --- a/python/ccdb/path_utils.py +++ b/python/ccdb/path_utils.py @@ -137,7 +137,7 @@ def parse_time(time_str="-1", max_time_by_default=True): month = int(tmp_str) # check for 30 day month - if month in [9, 4, 6, 10]: + if month in [4, 6, 9, 11]: day = 30 if month == 2: if year % 4 == 0 and year % 100 != 0 or year % 400 == 0: diff --git a/python/tests/integ_test_cli_manager.py b/python/tests/integ_test_cli_manager.py index 9c29f58..2c633e6 100644 --- a/python/tests/integ_test_cli_manager.py +++ b/python/tests/integ_test_cli_manager.py @@ -68,17 +68,64 @@ def tearDown(self): # restore stdout sys.stdout = self.saved_stdout + def clear_output(self): + # Reset output + self.output.seek(0) + self.output.truncate() + def test_context(self): """Test utils are loaded""" self.assertTrue(len(self.cli.utils) > 0) def test_cat(self): - """cat. General help""" + """cat. Return constants""" self.cli.process_command_line("cat /test/test_vars/test_table") self.assertIn("2.3", self.output.getvalue()) - def test_cat_user_set_variation(self): - """In non-interactive mode, cat should handle path without leading / as absolute anyway""" + def test_cat_by_id(self): + """cat. Return """ + self.cli.process_command_line("cat -a 2") + self.assertIn("6.0", self.output.getvalue()) + + self.clear_output() + + # Same but full flag + self.cli.process_command_line("cat --id=2") + self.assertIn("6.0", self.output.getvalue()) + + def test_cat_time(self): + """cat. Test specifying time to get particular constants""" + + # Test data has next records for test_table: + # /test/test_vars/test_table + # (ID) (Created) (Modified) (variation) (run range) (comments) + # 5 2012-10-30 23-48-43 2012-10-30 23-48-43 subtest 0-inf Test assignment for + # 4 2012-10-30 23-48-42 2012-10-30 23-48-42 default 0-inf Test assignment for + # 2 2012-08-30 23-48-42 2012-08-30 23-48-42 test 500-3000 Test assignment for + # 1 2012-07-30 23-48-42 2012-07-30 23-48-42 default 0-inf Test assignment for + + # It should return assignment with --id=1 + self.cli.process_command_line('cat -t 2012-08 /test/test_vars/test_table') + self.assertIn("1.11", self.output.getvalue()) + + def test_cat_run_variation(self): + """cat. If user sets ccdb -r -v ... it goes to context.current_run and context.current_variation. + They should be used as a fallback by command if no run or variation is given to command + """ + + # Test DB has a test data assignment for: + # variation: test + # runs: 500-2000 + # it has data: 1.0|2.0|3.0|4.0|5.0|6.0 + self.cli.context.current_variation = "default" # <= should not be used as cat overwrites variation + self.cli.context.current_run = 0 # <= should not be used as cat overwrites run + self.cli.process_command_line("cat -v test -r 600 /test/test_vars/test_table") + self.assertIn("6.0", self.output.getvalue()) + + def test_cat_default_run_variation(self): + """If user sets ccdb -r -v ... it goes to context.current_run and context.current_variation. + They should be used as a fallback by command if no run or variation is given to command + """ # Test DB has a test data assignment for: # variation: test @@ -89,6 +136,19 @@ def test_cat_user_set_variation(self): self.cli.process_command_line("cat /test/test_vars/test_table") self.assertIn("6.0", self.output.getvalue()) + def test_cat_request_overwrite(self): + """cat. If user sets ccdb -r -v cat ... But the requests sets different run and + and variation, then request has the top priority + """ + + # Test DB has a test data assignment for: + # variation: test + # runs: 500-2000 + # it has data: 1.0|2.0|3.0|4.0|5.0|6.0 + self.cli.context.current_variation = "default" # <= should not be used as cat overwrites variation + self.cli.context.current_run = 0 # <= should not be used as cat overwrites run + self.cli.process_command_line("cat -v default -r 0 /test/test_vars/test_table:600:test") + self.assertIn("6.0", self.output.getvalue()) def test_cat_not_abs_path(self): """In non-interactive mode, cat should handle path without leading / as absolute anyway""" diff --git a/python/tests/unit_test_path_utils.py b/python/tests/unit_test_path_utils.py index a0073fa..547e500 100644 --- a/python/tests/unit_test_path_utils.py +++ b/python/tests/unit_test_path_utils.py @@ -14,6 +14,11 @@ def test_parse_time(self): dt = ccdb.path_utils.parse_time("2012-11x13") # set different symbols as separators self.assertEqual(dt.strftime("%Y-%m-%d_%H-%M-%S"), "2012-11-13_23-59-59") + def test_parse_year_month(self): + # test of simple parse + dt = ccdb.path_utils.parse_time("2012-11") # set different symbols as separators + self.assertEqual(dt.strftime("%Y-%m-%d_%H-%M-%S"), "2012-11-30_23-59-59") + def test_full_parse_request(self): # test full request result = ccdb.path_utils.parse_request("/test/test_vars/test_table:100:mc:2012-11-13_12:37:55")