diff --git a/nspepi/check_invalid_config b/nspepi/check_invalid_config index efee007..e77c015 100755 --- a/nspepi/check_invalid_config +++ b/nspepi/check_invalid_config @@ -9,16 +9,16 @@ $ENV{PATH} = '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin'.$ENV use File::Basename; # checking if python and ply are present -# Output would be /var/python/bin/python2 if python2 is +# Output would be /var/python/bin/python if python is # present, otherwise output would be empty string. -my $python_version_string = `which python2 2> /dev/null`; +my $python_version_string = `which python 2> /dev/null`; if ($python_version_string eq "") { # Python2 is not installed - print "\nAs python2 is not present, we can't check for an invalid configuration\n"; + print "\nAs python is not present, we can't check for an invalid configuration\n"; exit; } -my $python_module_list = `python2 -m pip freeze 2> /dev/null`; +my $python_module_list = `python -m pip freeze 2> /dev/null`; if (!($python_module_list =~ m/\bply==/)) { # ply is not present print "\nAs required module PLY is not present, we can't check for an invalid configuration\n"; @@ -40,7 +40,7 @@ if (not -e $config_file) { my($filename, $dir_path) = fileparse($config_file); -my $exit_status = system("python2 /netscaler/nspepi2/config_check_main.py -f $config_file"); +my $exit_status = system("python /netscaler/nspepi2/config_check_main.py -f $config_file"); if ($exit_status != 0) { print "Error in checking config file: $exit_status"; exit; diff --git a/nspepi/nspepi b/nspepi/nspepi index 992401c..49aa417 100755 --- a/nspepi/nspepi +++ b/nspepi/nspepi @@ -5,16 +5,16 @@ # which accompany or are included with this software. # Checking if python and PLY are present -# Output would be /var/python/bin/python2 if python2 is +# Output would be /var/python/bin/python if python is # present, otherwise output would be empty string. -python_version_string=$(which python2 2> /dev/null) +python_version_string=$(which python 2> /dev/null) if [[ $python_version_string = "" ]] then - echo "As python2 is not present, we can't run the NSPEPI tool" + echo "As python is not present, we can't run the NSPEPI tool" exit fi -python_module_list=$(python2 -m pip freeze 2> /dev/null) +python_module_list=$(python -m pip freeze 2> /dev/null) if ! grep -q "\bply==" <<< $python_module_list then echo "As required module PLY is not present, we can't run the NSPEPI tool" diff --git a/nspepi/nspepi2/check_classic_configs.py b/nspepi/nspepi2/check_classic_configs.py index ca3bb79..b1e70dd 100644 --- a/nspepi/nspepi2/check_classic_configs.py +++ b/nspepi/nspepi2/check_classic_configs.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # Copyright 2021 Citrix Systems, Inc. All rights reserved. # Use of this software is governed by the license terms, if any, diff --git a/nspepi/nspepi2/check_classic_expr.py b/nspepi/nspepi2/check_classic_expr.py index c6902b4..901c0d9 100644 --- a/nspepi/nspepi2/check_classic_expr.py +++ b/nspepi/nspepi2/check_classic_expr.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # Copyright 2021 Citrix Systems, Inc. All rights reserved. # Use of this software is governed by the license terms, if any, @@ -33,6 +33,7 @@ def check_classic_expr(classic_expr): # Log the error message logging.error(exc.output) return None + nspepi_tool_output = nspepi_tool_output.decode() if nspepi_tool_output.startswith('ERROR:'): """old nspepi tool throws "ERROR: Expression is in blocked list of conversion" error for vpn client security expression. diff --git a/nspepi/nspepi2/cli_lex.py b/nspepi/nspepi2/cli_lex.py index 73d79f6..7e39e38 100644 --- a/nspepi/nspepi2/cli_lex.py +++ b/nspepi/nspepi2/cli_lex.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # Copyright 2021 Citrix Systems, Inc. All rights reserved. # Use of this software is governed by the license terms, if any, diff --git a/nspepi/nspepi2/cli_yacc.py b/nspepi/nspepi2/cli_yacc.py index a336fce..558db18 100644 --- a/nspepi/nspepi2/cli_yacc.py +++ b/nspepi/nspepi2/cli_yacc.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # Copyright 2021 Citrix Systems, Inc. All rights reserved. # Use of this software is governed by the license terms, if any, diff --git a/nspepi/nspepi2/config_check_main.py b/nspepi/nspepi2/config_check_main.py index 97e9278..086be9f 100755 --- a/nspepi/nspepi2/config_check_main.py +++ b/nspepi/nspepi2/config_check_main.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # Copyright 2021 Citrix Systems, Inc. All rights reserved. # Use of this software is governed by the license terms, if any, diff --git a/nspepi/nspepi2/convert_auth_cmd.py b/nspepi/nspepi2/convert_auth_cmd.py index 10ddaef..6737503 100644 --- a/nspepi/nspepi2/convert_auth_cmd.py +++ b/nspepi/nspepi2/convert_auth_cmd.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # Copyright 2021 Citrix Systems, Inc. All rights reserved. # Use of this software is governed by the license terms, if any, diff --git a/nspepi/nspepi2/convert_classic_expr.py b/nspepi/nspepi2/convert_classic_expr.py index c4814a3..8cc6e4b 100644 --- a/nspepi/nspepi2/convert_classic_expr.py +++ b/nspepi/nspepi2/convert_classic_expr.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # Copyright 2021 Citrix Systems, Inc. All rights reserved. # Use of this software is governed by the license terms, if any, @@ -60,6 +60,7 @@ def convert_classic_expr(classic_expr): # Log the error message logging.error(exc.output) return None + nspepi_tool_output = nspepi_tool_output.decode() if nspepi_tool_output.startswith('ERROR:'): """old nspepi tool throws "ERROR: Expression is in blocked list of conversion" error for vpn client security expression.""" diff --git a/nspepi/nspepi2/convert_cli_commands.py b/nspepi/nspepi2/convert_cli_commands.py index 94d3397..7c05640 100644 --- a/nspepi/nspepi2/convert_cli_commands.py +++ b/nspepi/nspepi2/convert_cli_commands.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # Copyright 2021 Citrix Systems, Inc. All rights reserved. # Use of this software is governed by the license terms, if any, @@ -774,6 +774,11 @@ def reprioritize_and_emit_4_level_dict(self, bind_dict): binds = module_bind_dict[bind_type] new_binds = self.reprioritize_binds(binds) for bind_info in new_binds: + if (bind_info.flow_type_direction and + bind_info.policy_type == "classic"): + self.update_tree_arg( + bind_info.parse_tree, "type", + bind_info.flow_type_direction.upper()) if common.pols_binds.is_bind_unsupported( bind_info.orig_cmd): logging.error( @@ -793,11 +798,6 @@ def reprioritize_and_emit_4_level_dict(self, bind_dict): bind_cmd_trees.append( "# {}".format(str(bind_info.parse_tree))) else: - if (bind_info.flow_type_direction and - bind_info.policy_type == "classic"): - self.update_tree_arg( - bind_info.parse_tree, "type", - bind_info.flow_type_direction.upper()) bind_cmd_trees.append(bind_info.parse_tree) return bind_cmd_trees @@ -849,7 +849,12 @@ def convert_cr_vserver(self, commandParseTree): vserver_protocol_dict - dict to store protocol as value to the vserver name as key """ - cr_protocol = commandParseTree.positional_value(1).value + + if commandParseTree.keyword_exists('td'): + cr_protocol = str(commandParseTree.keyword_value('td')[1]) + else: + cr_protocol = commandParseTree.positional_value(1).value + crv_name = commandParseTree.positional_value(0).value vserver_protocol_dict[crv_name] = cr_protocol.upper() return [commandParseTree] @@ -1733,7 +1738,12 @@ def convert_cs_vserver(self, commandParseTree): vserver_protocol_dict - dict to store protocol as value to the vserver name as key """ - cs_protocol = commandParseTree.positional_value(1).value + + if commandParseTree.keyword_exists('td'): + cs_protocol = str(commandParseTree.keyword_value('td')[1]) + else: + cs_protocol = commandParseTree.positional_value(1).value + csv_name = commandParseTree.positional_value(0).value vserver_protocol_dict[csv_name] = cs_protocol.upper() commandParseTree = ContentSwitching.convert_adv_expr_list( @@ -1808,54 +1818,51 @@ def convert_policy(self, commandParseTree): prefix_val = None suffix = None url_expr = commandParseTree.keyword_value('url')[0].value - if url_expr.endswith('.'): + last_url_expr = url_expr.rsplit('/', 1) + converted_url_expr = 'HTTP.REQ.URL.PATH.EQ("' + \ + url_expr + '")' + if ((last_url_expr[1] == '') or + (('.' not in last_url_expr[1]) and + ('*' not in last_url_expr[1]))): + converted_url_expr = 'HTTP.REQ.URL.PATH.EQ(("' + \ + url_expr + '." + HTTP.REQ.URL.SUFFIX).' + \ + 'STRIP_END_CHARS("."))' + elif url_expr.endswith('.'): converted_url_expr = 'HTTP.REQ.URL.PATH.EQ("' + \ - url_expr + '.")' + url_expr + '")' + elif url_expr.endswith('*'): + if (url_expr[-3:] == '*.*'): + converted_url_expr = 'HTTP.REQ.URL.PATH.STARTSWITH("' + \ + url_expr[0: -3] + '")' + elif (url_expr[-2:] == '.*'): + converted_url_expr = 'HTTP.REQ.URL.PATH.EQ(("' + \ + url_expr[0:-1] + \ + '" + HTTP.REQ.URL.SUFFIX).STRIP_END_CHARS("."))' + elif (url_expr == '/*'): + converted_url_expr = 'true' + else: + converted_url_expr = 'HTTP.REQ.URL.PATH.STARTSWITH("' + \ + url_expr[0:-1] + '")' else: - prefix_suffix = url_expr.rsplit('.', 1) + prefix_suffix = last_url_expr[1].rsplit('.', 1) if len(prefix_suffix) is 1: - """ No suffix is present in URL.""" - prefix = prefix_suffix[0] - suffix = None - if prefix.endswith('*'): - prefix_val = prefix[:-1] + converted_url_expr = 'HTTP.REQ.URL.PATH.EQ(("' + \ + url_expr + \ + '." + HTTP.REQ.URL.SUFFIX).STRIP_END_CHARS("."))' else: """ Suffix is present in URL.""" + prefix_suffix = url_expr.rsplit('.', 1) prefix = prefix_suffix[0] suffix = prefix_suffix[1] - """ - If URL is abc..*.html, then - in classic code, we don't check - one dot before *, and this happens - only if there is some suffix. - """ - if prefix.endswith('*'): - prefix_val = prefix[:-1] - if prefix_val.endswith('.'): - prefix_val = prefix_val[:-1] - - if suffix and (prefix != '/') and (not prefix.endswith('*')): - converted_url_expr = 'HTTP.REQ.URL.PATH.EQ("' + \ - url_expr + '")' - elif (suffix is None) and (not prefix.endswith('*')): - converted_url_expr = 'HTTP.REQ.URL.PATH.EQ(("' + \ - prefix + '." + HTTP.REQ.URL.SUFFIX).' + \ - 'STRIP_END_CHARS("."))' - elif (prefix == '/*') and (suffix is not None): - converted_url_expr = 'HTTP.REQ.URL.SUFFIX.EQ("' + \ - suffix + '")' - elif (prefix.endswith('*')) and (suffix is not None): - converted_url_expr = '(HTTP.REQ.URL.STARTSWITH("' + \ - prefix_val + '") && HTTP.REQ.URL.SUFFIX.EQ("' + \ - suffix + '"))' - elif (prefix == '/*'): - converted_url_expr = 'true' - elif (prefix.endswith('*')): - converted_url_expr = 'HTTP.REQ.URL.STARTSWITH("' + \ - prefix_val + '")' - elif (suffix is not None) and (prefix == '/'): - converted_url_expr = 'HTTP.REQ.URL.SUFFIX.EQ("' + \ - suffix + '")' + if prefix == '/': + converted_url_expr = 'HTTP.REQ.URL.PATH.EQ(("/."' + \ + ' + HTTP.REQ.URL.SUFFIX).STRIP_END_CHARS(' + \ + '"."))' + elif prefix.endswith('*'): + converted_url_expr = '(HTTP.REQ.URL.PATH.STARTSWITH' + \ + '("' + prefix[0:-1] + \ + '") && HTTP.REQ.URL.SUFFIX.EQ("' + \ + suffix + '"))' if commandParseTree.keyword_exists('domain'): domain_name = commandParseTree.keyword_value('domain')[0] \ diff --git a/nspepi/nspepi2/convert_cmp_cmd.py b/nspepi/nspepi2/convert_cmp_cmd.py index 3aaac56..f585e7f 100644 --- a/nspepi/nspepi2/convert_cmp_cmd.py +++ b/nspepi/nspepi2/convert_cmp_cmd.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # Copyright 2021 Citrix Systems, Inc. All rights reserved. # Use of this software is governed by the license terms, if any, diff --git a/nspepi/nspepi2/convert_filter_command.py b/nspepi/nspepi2/convert_filter_command.py index 1bbd531..66dbf71 100644 --- a/nspepi/nspepi2/convert_filter_command.py +++ b/nspepi/nspepi2/convert_filter_command.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # Copyright 2021 Citrix Systems, Inc. All rights reserved. # Use of this software is governed by the license terms, if any, @@ -648,7 +648,7 @@ def convert_filter_policy(self, policy_parse_tree): # having value as prebody or postbody Since they belong to # html injection family return self.return_original_input(original_cmd, pol_obj) - for dict_key, dict_value in self._actionTypeName.iteritems(): + for dict_key, dict_value in self._actionTypeName.items(): """ Extract key and value from stored _actionTypeName dictionary through action convertion """ if policy_action not in dict_value: diff --git a/nspepi/nspepi2/convert_lb_cmd.py b/nspepi/nspepi2/convert_lb_cmd.py index 0267d1f..c0be352 100644 --- a/nspepi/nspepi2/convert_lb_cmd.py +++ b/nspepi/nspepi2/convert_lb_cmd.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # Copyright 2021 Citrix Systems, Inc. All rights reserved. # Use of this software is governed by the license terms, if any, diff --git a/nspepi/nspepi2/convert_patclass_commands.py b/nspepi/nspepi2/convert_patclass_commands.py index e0ce52a..02bdc33 100644 --- a/nspepi/nspepi2/convert_patclass_commands.py +++ b/nspepi/nspepi2/convert_patclass_commands.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # Copyright 2021 Citrix Systems, Inc. All rights reserved. # Use of this software is governed by the license terms, if any, diff --git a/nspepi/nspepi2/convert_responder_command.py b/nspepi/nspepi2/convert_responder_command.py index d44a53f..593f744 100644 --- a/nspepi/nspepi2/convert_responder_command.py +++ b/nspepi/nspepi2/convert_responder_command.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # Copyright 2021 Citrix Systems, Inc. All rights reserved. # Use of this software is governed by the license terms, if any, diff --git a/nspepi/nspepi2/convert_rewrite_command.py b/nspepi/nspepi2/convert_rewrite_command.py index cdf7ec4..6856bd0 100644 --- a/nspepi/nspepi2/convert_rewrite_command.py +++ b/nspepi/nspepi2/convert_rewrite_command.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # Copyright 2021 Citrix Systems, Inc. All rights reserved. # Use of this software is governed by the license terms, if any, diff --git a/nspepi/nspepi2/nspepi_common.py b/nspepi/nspepi2/nspepi_common.py index 9dd6781..ac48618 100644 --- a/nspepi/nspepi2/nspepi_common.py +++ b/nspepi/nspepi2/nspepi_common.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # Copyright 2021 Citrix Systems, Inc. All rights reserved. # Use of this software is governed by the license terms, if any, @@ -565,7 +565,7 @@ def do_priority_analysis(self, global_list, local_list, else: # no more valid states so all priorities including # and after current priority cannot be converted - res = list(itertools.chain(*(combined.values()))) + res.extend(combined[prio]) break o.global_type = g_types[state] res_gtypes.append(o) @@ -611,30 +611,23 @@ def analyze_vserver_priorities(self): gbinds = PoliciesAndBinds.global_binds for gmodule in gbinds: for gbind_type in gbinds[gmodule]: + locals_list = [] if local_binds: for entity_type in local_binds: - locals_list = [] if (gmodule in local_binds[entity_type] and gbind_type in local_binds[entity_type][gmodule]): # module and bind_type match for global and local locals_list += ( local_binds[entity_type][gmodule][gbind_type]) - logging.debug( - "do_priority_analysis() for {} {}" - "".format(gmodule, gbind_type)) - unsupp, updated_gtypes = self.do_priority_analysis( - gbinds[gmodule][gbind_type], locals_list, - gmodule in PoliciesAndBinds. - get_skip_global_override()) - unsupported.update(unsupp) - updated_global_types += updated_gtypes - else: - unsupp, updated_gtypes = self.do_priority_analysis( - gbinds[gmodule][gbind_type], [], - gmodule in PoliciesAndBinds. - get_skip_global_override()) - unsupported.update(unsupp) - updated_global_types += updated_gtypes + logging.debug( + "do_priority_analysis() for {} {}" + "".format(gmodule, gbind_type)) + unsupp, updated_gtypes = self.do_priority_analysis( + gbinds[gmodule][gbind_type], locals_list, + gmodule in PoliciesAndBinds. + get_skip_global_override()) + unsupported.update(unsupp) + updated_global_types += updated_gtypes # store analysis results res = PoliciesAndBinds.priority_analysis_results for bindobj in unsupported: @@ -939,12 +932,13 @@ def do_priority_analysis_for_all_users_groups(self, user_list, group_list): weights = collections.defaultdict(set) [weights[int(self.get_group(o.entity_name).weight)].add(o) for o in group_list] - for v in weights.itervalues(): - if len(set([o.entity_name for o in v])) > 1: + for v in weights.values(): + same_weight_group_set = set([o.entity_name for o in v]) + if len(same_weight_group_set) > 1: logging.error("Groups: {} having the same weight and bindings" " have no defined ordering in Advanced Policy" " evaluation.".format( - ", ".join(set([o.entity_name for o in v])))) + ", ".join(sorted(same_weight_group_set)))) res.update(v) logging.debug("do_priority_analysis_for_all_users_groups(): ") logging.debug("\nusers: {}\n\ngroups: {}\n\nunsupported: {}" diff --git a/nspepi/nspepi2/nspepi_helper b/nspepi/nspepi2/nspepi_helper index d8be9d4..bd3f69b 100755 --- a/nspepi/nspepi2/nspepi_helper +++ b/nspepi/nspepi2/nspepi_helper @@ -10,7 +10,7 @@ # # The upgraded command might have more than 8191 chars based on the # length of the classic command. These commands will fail while adding -# on ADC +# on Citrix ADC # # For better performance and to take full advantage of advanced syntax, # manually we have to optimize after conversion. @@ -556,7 +556,7 @@ sub identifyExpressions if ($expr_params =~ /^\s+-netmask\s+(\d+\.\d+\.\d+.\d+)(.*)$/is) { my $netmask = $1; $expr_params=$2; - #Convert netmask for PI syntax. + #Convert netmask for Advanced syntax. $netmask = parseNetmask($netmask); $advanced = $advanced.'.IN_SUBNET('.$ip_addr.'/'.$netmask.')'; } @@ -589,14 +589,46 @@ sub identifyExpressions } else { my $ARG = extractArgument(); - if ($ARG !~ /\*/) { - $expr_params=$expression_temp; - parseTextOperator($OPERATOR); - return; + my $last_index_of_slash = rindex($ARG, "/"); + my $url_after_last_slash = substr($ARG, $last_index_of_slash + 1); + if (($url_after_last_slash eq '') || (($url_after_last_slash !~ /\*/) && ($url_after_last_slash !~ /\./))) { + $advanced = 'HTTP.REQ.URL.PATH.EQ(('.$qu.$ARG.'.'.$qu.' + HTTP.REQ.URL.SUFFIX).STRIP_END_CHARS('.$qu.'.'.$qu.'))'; + } else { + $advanced = 'HTTP.REQ.URL.PATH.EQ('.$qu.$ARG.$qu.')'; + my $last_char = substr($ARG, -1); + if ($last_char eq '.') { + # No need to do anything. + } elsif ($last_char eq '*') { + my $last_str = substr($ARG, -3); + if ($last_str eq '*.*') { + $advanced = 'HTTP.REQ.URL.PATH.STARTSWITH('.$qu.substr($ARG, 0, -3).$qu.')'; + } else { + $last_str = substr($ARG, -2); + if ($last_str eq '.*') { + $advanced = 'HTTP.REQ.URL.PATH.EQ(('.$qu.substr($ARG, 0, -1).$qu.'+ HTTP.REQ.URL.SUFFIX).STRIP_END_CHARS('.$qu.'.'.$qu.'))'; + } elsif ($ARG eq '/*') { + $advanced = 'true'; + } else { + $advanced = 'HTTP.REQ.URL.PATH.STARTSWITH('.$qu.substr($ARG, 0, -1).$qu.')'; + } + } + } else { + my $last_index_of_dot = rindex($url_after_last_slash, "."); + if ($last_index_of_dot != -1) { + $last_index_of_dot = rindex($ARG, "."); + my $prefix = substr($ARG, 0, $last_index_of_dot); + my $prefix_last_char = substr($prefix, -1); + my $suffix = substr($ARG, $last_index_of_dot + 1); + if ($prefix eq "/") { + $advanced = 'HTTP.REQ.URL.PATH.EQ(('.$qu.'/.'.$qu.'+ HTTP.REQ.URL.SUFFIX).STRIP_END_CHARS('.$qu.'.'.$qu.'))'; + } elsif ($prefix_last_char eq "*") { + $advanced = '(HTTP.REQ.URL.PATH.STARTSWITH('.$qu.substr($prefix, 0, -1).$qu.') && HTTP.REQ.URL.SUFFIX.EQ('.$qu.$suffix.$qu.'))'; + } + } else { + $advanced = 'HTTP.REQ.URL.PATH.EQ(('.$qu.$ARG.'.'.$qu.'+ HTTP.REQ.URL.SUFFIX).STRIP_END_CHARS('.$qu.'.'.$qu.'))'; + } + } } - $ARG =~ s/\./\\./; - $ARG =~ s/\*/(.*)/g; - $advanced = $advanced.'.REGEX_MATCH(re#'.$ARG.'#)'; if ($OPERATOR eq '!=') { $advanced =$advanced.'.NOT'; } diff --git a/nspepi/nspepi2/nspepi_main.py b/nspepi/nspepi2/nspepi_main.py index 6734219..3267544 100755 --- a/nspepi/nspepi2/nspepi_main.py +++ b/nspepi/nspepi2/nspepi_main.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # Copyright 2021 Citrix Systems, Inc. All rights reserved. # Use of this software is governed by the license terms, if any, @@ -255,6 +255,9 @@ def main(): # convert ns config file elif args.infile is not None: new_path = os.path.join(conf_file_path, "new_" + conf_file_name) + if not os.path.exists(args.infile): + print("\nInput file " + args.infile + " does not exist") + return with open(args.infile, 'r') as infile: with open(new_path, 'w') as outfile: convert_config_file(infile, outfile, args.verbose) diff --git a/nspepi/nspepi2/nspepi_parse_tree.py b/nspepi/nspepi2/nspepi_parse_tree.py index bdda52f..8ce3c69 100644 --- a/nspepi/nspepi2/nspepi_parse_tree.py +++ b/nspepi/nspepi2/nspepi_parse_tree.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # Copyright 2021 Citrix Systems, Inc. All rights reserved. # Use of this software is governed by the license terms, if any, diff --git a/nspepi/nspepi2/pi_lex.py b/nspepi/nspepi2/pi_lex.py index bc98eb1..0875a7f 100644 --- a/nspepi/nspepi2/pi_lex.py +++ b/nspepi/nspepi2/pi_lex.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # Copyright 2021 Citrix Systems, Inc. All rights reserved. # Use of this software is governed by the license terms, if any, @@ -10,7 +10,7 @@ class PILex(object): """ - Class to parse PI expressions. + Class to parse Advanced expressions. """ @staticmethod