def __init__(self, cnt, version):
        self.version = str(version)

        self.version = self.version.strip().split('.')

        test(len(self.version) == 2, err.InvalidBopMinVers, (cnt, version))

        try:
            for i, v in enumerate(self.version):
                self.version[i] = int(v)
        except:
            raise err.InvalidBopMinVers(cnt, version)

        try:
            v_maj = int(current_bop_version_major)
            v_min = int(current_bop_version_minor)
        except:
            raise err.Bug(cnt, None)

        if v_maj < self.version[0]:
            raise err.InsufficientBopVersion(cnt, version.strip())
        elif v_maj == self.version[0]:
            if v_min < self.version[1]:
                raise err.InsufficientBopVersion(cnt, version.strip())
        else:
            ## TODO (?) should issue warning??
            pass
Example #2
0
    def set_numeric_default_val(self, cnt):
        if self.arg_type == "INT":
            invalid_error = err.InvalidIntDefaultVal
            out_of_range_error = err.OutOfRangeIntDefaultVal
        elif self.arg_type == "FLOAT":
            invalid_error = err.InvalidFloatDefaultVal
            out_of_range_error = err.OutOfRangeFloatDefaultVal
        else:
            raise err.Bug(cnt, "")

        self.default_arg = check.is_empty_or_none(self.default_arg)
        if self.default_arg != None:
            try:
                if self.arg_type == "INT":
                    def_val = long(self.default_arg)
                elif self.arg_type == "FLOAT":
                    def_val = float(self.default_arg)
            except ValueError:
                raise invalid_error(cnt, self.default_arg)

            self.default_arg = self.default_arg.strip()

            test(
                check.is_in_range(def_val, self.arg_range, self.open_boundary),
                out_of_range_error, (cnt, def_val))
Example #3
0
    def print_check_optarg_range_block(self, outfile):
        """
		Prints the bash check range line for the given option
		"""
        if self.has_arg and self.arg_range != None and self.arg_range != [
                None, None
        ]:
            outfile.write("for BASH_OPTPARSE_AUXVAR in \"${" + self.name +
                          "[@]}\";\n")
            outfile.write("do\n")

            if self.arg_type == "INT" or self.arg_type == "FLOAT":
                if self.open_boundary[0] == False:
                    b0 = "["
                else:
                    b0 = "("
                if self.open_boundary[1] == False:
                    b1 = "]"
                else:
                    b1 = ")"
                if self.arg_range[0] != None:
                    sr0 = str(self.arg_range[0])
                else:
                    sr0 = "-INF"
                if self.arg_range[-1] != None:
                    sr1 = str(self.arg_range[-1])
                else:
                    sr1 = "INF"
                if len(self.arg_range) == 3:
                    srst = str(self.arg_range[1])
                    srst_out = str(self.arg_range[1]) + ":"
                else:
                    srst = "0"
                    srst_out = ""
                outfile.write( \
                 "\tcheck_is_in_range \"$BASH_OPTPARSE_AUXVAR\" " + \
                 "\"" + b0 + "\"" + " " + sr0 + " " + srst + " " + sr1 + " " + "\"" + b1 + "\"" + \
                 " || " + self.abort_pre() + "abort \"out of range argument to option " + \
                 self.opt_name + ": $BASH_OPTPARSE_AUXVAR" + \
                 " (range is " + b0 + sr0 + ":" + srst_out + sr1 + b1 + \
                 ")\" " + str(self.settings.err_code_opt_range) + \
                 self.abort_post(self.settings.err_code_opt_range) + "\n")
            elif self.arg_type == "STRING":
                outfile.write("\tif ! bop_pygrep '^(" + self.arg_range +
                              ")$' \"$BASH_OPTPARSE_AUXVAR\"\n")
                outfile.write("\tthen\n")
                outfile.write("\t\t" + self.abort_pre() + "abort \"Invalid argument to option " + self.opt_name + \
                 ": $BASH_OPTPARSE_AUXVAR (must match regex: /" + self.arg_range + "/)\" " + \
                 str(self.settings.err_code_opt_range) + \
                 self.abort_post(self.settings.err_code_opt_range) + "\n")
                outfile.write("\tfi\n")
            else:
                raise err.Bug(cnt, "")
            outfile.write("done\n")
            outfile.write("\n")
Example #4
0
    def parse_numeric_range(self, cnt):
        if self.arg_type == "INT":
            range_error = err.InvalidIntRange
        elif self.arg_type == "FLOAT":
            range_error = err.InvalidFloatRange
        else:
            raise err.Bug(cnt, "")

        ar = self.arg_range.strip()
        if ar == "":
            ar = ":"
        if ar[0] in "](":
            self.open_boundary[0] = True
        if ar[-1] in "[)":
            self.open_boundary[1] = True
        if ar[0] in "[](" and ar[-1] in "[])":
            ar = ar[1:-1]
        ar = ar.split(':')
        for i in range(len(ar)):
            if len(ar[i].strip()) == 0:
                ar[i] = None
            elif (i == 0 and ar[i].strip().upper() == "-INF") or \
             (i == len(ar) - 1 and ar[i].strip().upper() == "INF"):
                ar[i] = None
            elif (ar[i].strip().upper() == "NONE"):
                ar[i] = None
            else:
                try:
                    exec("ar[i] = " + ar[i])
                except (NameError, SyntaxError):
                    raise range_error(cnt, self.arg_range)
        self.arg_range = ar

        #try:
        #exec "self.arg_range = " + self.arg_range
        #except (NameError, SyntaxError):
        #raise range_error(cnt, self.arg_range)

        test(isinstance(self.arg_range, list), range_error,
             (cnt, self.arg_range))
        test(
            len(self.arg_range) == 2 or len(self.arg_range) == 3, range_error,
            (cnt, self.arg_range))

        if self.arg_range[0] == None:
            self.open_boundary[0] = True
        if self.arg_range[-1] == None:
            self.open_boundary[1] = True
    def __init__(self, infile):
        self.description = ""
        self.opt_list = []
        self.usage_line = []
        self.arg_list = []
        self.vararg = None
        self.version = []
        self.settings = settings.BopSettings()

        current_block = None
        optional_arg_given = False

        settings_block_given = False
        description_block_given = False
        version_block_given = False
        options_block_given = False
        arguments_block_given = False

        insert_space_in_description = False
        insert_space_in_version = False

        opt_reader = preparser.LinePreParser()

        cnt = err.ParseCount()

        for l in infile.readlines():
            cnt.inc()
            cnt.line = l
            line = opt_reader.parse_line(cnt, l)
            cnt.line = line
            if len(line) == 0:
                continue

            if current_block == None:
                if len(line) > 1:
                    raise err.InvalidBlockBeginLine(cnt, line)
                line[0] = line[0].upper()
                if line[0] == "SETTINGS_BEGIN":
                    test(not settings_block_given, err.DuplicateBlock,
                         (cnt, "SETTINGS"))
                    current_block = "SETTINGS_BLOCK"
                    settings_block_given = True
                elif line[0] == "DESCRIPTION_BEGIN":
                    test(not description_block_given, err.DuplicateBlock,
                         (cnt, "DESCRIPTION"))
                    current_block = "DESCRIPTION_BLOCK"
                    description_block_given = True
                elif line[0] == "VERSION_BEGIN":
                    test(not version_block_given, err.DuplicateBlock,
                         (cnt, "VERSION"))
                    current_block = "VERSION_BLOCK"
                    version_block_given = True
                elif line[0] == "OPTIONS_BEGIN":
                    test(not options_block_given, err.DuplicateBlock,
                         (cnt, "OPTIONS"))
                    current_block = "OPTIONS_BLOCK"
                    options_block_given = True
                elif line[0] == "ARGUMENTS_BEGIN":
                    test(not arguments_block_given, err.DuplicateBlock,
                         (cnt, "ARGUMENTS"))
                    current_block = "ARGUMENTS_BLOCK"
                    arguments_block_given = True
                else:
                    raise err.UnknownDescriptor(cnt, line[0])
            elif current_block == "SETTINGS_BLOCK":
                if line[0] == "SETTINGS_END":
                    current_block = None
                    continue
                if line[0] == "REQUIRED_VERSION":
                    test(
                        len(line) == 2, err.InvalidBopMinVersLine,
                        (cnt, len(line)))
                    settings.BopRequiredVersionChecker(cnt, *(line[1:]))
                elif line[0] == "WRAP_WIDTH":
                    test(
                        len(line) == 2, err.InvalidBopWrapWidthLine,
                        (cnt, len(line)))
                    try:
                        self.settings.wrap_width = int(line[1])
                    except:
                        raise err.InvalidBopWrapWidth(cnt, line[1])
                    test(self.settings.wrap_width >= 30,
                         err.InvalidBopWrapWidth,
                         (cnt, self.settings.wrap_width))
                elif line[0] == "AUTO_SHORT_OPTS":
                    test(
                        len(line) == 2, err.InvalidBopAutoShortOptsLine,
                        (cnt, len(line)))
                    try:
                        exec("self.settings.auto_short_opts = " +
                             line[1].capitalize())
                    except (NameError, SyntaxError):
                        raise err.InvalidBopAutoShortOpts(cnt, line[1])
                    test(isinstance(self.settings.auto_short_opts, bool),
                         err.InvalidBopAutoShortOpts, (cnt, line[1]))
                elif line[0] == "ONE_DASH_LONG_OPTS":
                    test(
                        len(line) == 2, err.InvalidBopOneDashLongOptsLine,
                        (cnt, len(line)))
                    try:
                        exec("self.settings.one_dash_long_opts = " +
                             line[1].capitalize())
                    except (NameError, SyntaxError):
                        raise err.InvalidBopOneDashLongOpts(cnt, line[1])
                    test(isinstance(self.settings.one_dash_long_opts, bool),
                         err.InvalidBopOneDashLongOpts, (cnt, line[1]))
                elif line[0] == "IN_FUNCTION":
                    test(
                        len(line) == 2, err.InvalidBopInFunctionLine,
                        (cnt, len(line)))
                    try:
                        exec("self.settings.in_function = " +
                             line[1].capitalize())
                    except (NameError, SyntaxError):
                        raise err.InvalidBopInFunction(cnt, line[1])
                    test(isinstance(self.settings.in_function, bool),
                         err.InvalidBopInFunction, (cnt, line[1]))
                elif line[0] == "ERR_CODE_OPT_INVALID":
                    test(
                        len(line) == 2, err.InvalidBopErrCodeLine,
                        (cnt, len(line)))
                    try:
                        self.settings.err_code_opt_invalid = int(line[1])
                    except:
                        raise err.InvalidBopErrCode(cnt, line[1])
                elif line[0] == "ERR_CODE_OPT_TYPE":
                    test(
                        len(line) == 2, err.InvalidBopErrCodeLine,
                        (cnt, len(line)))
                    try:
                        self.settings.err_code_opt_type = int(line[1])
                    except:
                        raise err.InvalidBopErrCode(cnt, line[1])
                elif line[0] == "ERR_CODE_OPT_RANGE":
                    test(
                        len(line) == 2, err.InvalidBopErrCodeLine,
                        (cnt, len(line)))
                    try:
                        self.settings.err_code_opt_range = int(line[1])
                    except:
                        raise err.InvalidBopErrCode(cnt, line[1])
                elif line[0] == "ERR_CODE_ARG_NUM":
                    test(
                        len(line) == 2, err.InvalidBopErrCodeLine,
                        (cnt, len(line)))
                    try:
                        self.settings.err_code_arg_num = int(line[1])
                    except:
                        raise err.InvalidBopErrCode(cnt, line[1])

                else:
                    raise err.UnknownSetting(cnt, line[0])
            elif current_block == "DESCRIPTION_BLOCK":
                if line[0] == "DESCRIPTION_END":
                    current_block = None
                    continue
                for i in range(len(line)):
                    if len(line[i]) == 0:
                        continue
                    if insert_space_in_description and not line[i][0].isspace(
                    ):
                        self.description += " "
                    self.description += line[i]
                    if line[i][-1].isspace():
                        insert_space_in_description = False
                    else:
                        insert_space_in_description = True
            elif current_block == "VERSION_BLOCK":
                if line[0] == "VERSION_END":
                    current_block = None
                    continue
                #test(len(line) == 1, err.InvalidVersLine, (cnt, len(line)))
                insert_space_in_version = False
                vline = ""
                for i in range(len(line)):
                    if len(line[i]) == 0:
                        continue
                    if insert_space_in_version and not line[i][0].isspace():
                        vline += " "
                    vline += line[i]
                    if line[i][-1].isspace():
                        insert_space_in_version = False
                    else:
                        insert_space_in_version = True
                self.version.append(vline)
            elif current_block == "OPTIONS_BLOCK":
                if line[0] == "OPTIONS_END":
                    current_block = None
                    continue
                test(
                    len(line) == opt.BopOption.required_args,
                    err.InvalidOptLine, (cnt, len(line)))
                myopt = opt.BopOption(cnt, self.settings, *line)

                test(
                    myopt.opt_name_alt == None
                    or myopt.opt_name != myopt.opt_name_alt, err.DuplicateOpt,
                    (cnt, myopt.opt_name))
                test(
                    myopt.short == None or myopt.short_alt == None
                    or myopt.short != myopt.short_alt, err.DuplicateShortOpt,
                    (cnt, myopt.short))

                for o in self.opt_list:
                    test(myopt.name != o.name, err.DuplicateOpt,
                         (cnt, myopt.name))
                    test(myopt.short == None or myopt.short != o.short,
                         err.DuplicateShortOpt, (cnt, myopt.short))

                    test(
                        myopt.opt_name_alt == None
                        or myopt.opt_name_alt != o.opt_name, err.DuplicateOpt,
                        (cnt, myopt.opt_name_alt))
                    test(
                        o.opt_name_alt == None
                        or myopt.opt_name != o.opt_name_alt, err.DuplicateOpt,
                        (cnt, myopt.opt_name))
                    test(
                        myopt.opt_name_alt == None or o.opt_name_alt == None
                        or myopt.opt_name_alt != o.opt_name_alt,
                        err.DuplicateOpt, (cnt, myopt.opt_name_alt))

                    test(
                        myopt.short_alt == None or o.short == None
                        or myopt.short_alt != o.short, err.DuplicateShortOpt,
                        (cnt, myopt.short_alt))
                    test(
                        myopt.short == None or o.short_alt == None
                        or myopt.short != o.short_alt, err.DuplicateShortOpt,
                        (cnt, myopt.short))
                    test(
                        myopt.short_alt == None or o.short_alt == None
                        or myopt.short_alt != o.short_alt,
                        err.DuplicateShortOpt, (cnt, myopt.short_alt))
                self.opt_list.append(myopt)
            elif current_block == "ARGUMENTS_BLOCK":
                if line[0] == "ARGUMENTS_END":
                    current_block = None
                    continue
                if line[0].upper() == "VARARGS" or line[0] == "@":
                    test(self.vararg == None, err.MultipleVararg, (cnt, ""))
                    test(
                        len(line) == arg.BopVararg.required_args,
                        err.InvalidVarargLine, (cnt, len(line)))
                    myvarg = arg.BopVararg(cnt, self.settings, *line)
                    if not myvarg.mandatory:
                        optional_arg_given = True
                    else:
                        test(not optional_arg_given, err.MandVarargAfterOptArg,
                             (cnt, ""))
                    self.vararg = myvarg
                else:
                    test(self.vararg == None, err.ArgAfterVararg, (cnt, ""))
                    test(
                        len(line) == arg.BopArgument.required_args,
                        err.InvalidArgLine, (cnt, len(line)))
                    myarg = arg.BopArgument(cnt, self.settings, *line)
                    if not myarg.mandatory:
                        optional_arg_given = True
                    else:
                        test(not optional_arg_given, err.MandArgAfterOptArg,
                             (cnt, ""))
                    for a in self.arg_list:
                        test(myarg.name != a.name, err.DuplicateArg,
                             (cnt, myarg.name))
                    self.arg_list.append(myarg)
            else:
                raise err.Bug(cnt, "")

        test(current_block == None, err.BlockNotClosed, (cnt, current_block))

        for o in self.opt_list:
            for a in self.arg_list:
                test(o.name != a.name, err.DuplicateOptArg, (cnt, o.name))

        if self.settings.auto_short_opts:
            for o in self.opt_list:
                if (o.short != None or o.force_noshort) and \
                 (o.name_alt == None or o.short_alt != None or o.force_noshort_alt):
                    continue
                if not (o.short != None or o.force_noshort):
                    for c in o.name:
                        if not check.optname_short(c):
                            continue
                        found = False
                        for o1 in self.opt_list:
                            if c == o1.short or c == o1.short_alt:
                                found = True
                                break
                        if not found:
                            o.short = c
                            break
                if not (o.name_alt == None or o.short_alt != None
                        or o.force_noshort_alt):
                    for c in o.name_alt:
                        if not check.optname_short(c):
                            continue
                        found = False
                        for o1 in self.opt_list:
                            if c == o1.short or c == o1.short_alt:
                                found = True
                                break
                        if not found:
                            o.short_alt = c
                            break

        for o in self.opt_list:
            self.usage_line.append(o.gen_usage_line())
            if o.name_alt != None:
                self.usage_line.append(o.gen_usage_line_alt())

        self.usage_line.append(
            ["--version", "output version information and exit"])
        self.usage_line.append(["--help", "print this help and exit"])

        if len(self.version) == 0:
            self.version.append("Version information unspecified")

        if not self.settings.in_function:
            self.exit_command = "exit"
        else:
            self.exit_command = "BASH_OPTPARSE_EARLY_RETURN=true; return"