Repository: locustio/locust
File: locust/argument_parser.py (Python)

Code before:
        if not options.locustfile.endswith(".py"):
            note_about_file_endings = "Ensure your locustfile ends with '.py' or is a directory with parsed_paths. "
        sys.stderr.write(
            f"Could not find '{user_friendly_locustfile_name}'. {note_about_file_endings}See --help for available options.\n"
        )
        sys.exit(1)

    return parsed_paths


# A hack for setting up an action that raises ArgumentError with configurable error messages.
# This is meant to be used to immediately block use of deprecated arguments with some helpful messaging.


def raise_argument_type_error(err_msg):
    class ErrorRaisingAction(configargparse.Action):
        def __call__(self, parser, namespace, values, option_string=None):
            raise configargparse.ArgumentError(self, err_msg)

    return ErrorRaisingAction


# Definitions for some "types" to use with the arguments


def timespan(time_str):
    try:
        return parse_timespan(time_str)
    except ValueError as e:
        raise configargparse.ArgumentTypeError(str(e))


def positive_integer(string):
    try:
        value = int(string)
    except ValueError:
        raise configargparse.ArgumentTypeError(f"invalid int value: '{string}'")

    if value < 1:
        raise configargparse.ArgumentTypeError(
            f"Invalid --expect-workers argument ({value}), must be a positive number"
        )

    return value


def json_user_config(string):
    try:
        if string.endswith(".json"):
            with open(string) as file:
                user_config = json.load(file)

Review comment (suggestion):
Cool stuff! Probably wanna add a type hint for the return type at least?

If you do, does the hint carry over to when people do environment.parsed_options.stop_timeout? That'd be cool...

Code after:
        if not options.locustfile.endswith(".py"):
            note_about_file_endings = "Ensure your locustfile ends with '.py' or is a directory with parsed_paths. "
        sys.stderr.write(
            f"Could not find '{user_friendly_locustfile_name}'. {note_about_file_endings}See --help for available options.\n"
        )
        sys.exit(1)

    return parsed_paths


# A hack for setting up an action that raises ArgumentError with configurable error messages.
# This is meant to be used to immediately block use of deprecated arguments with some helpful messaging.


def raise_argument_type_error(err_msg):
    class ErrorRaisingAction(configargparse.Action):
        def __call__(self, parser, namespace, values, option_string=None):
            raise configargparse.ArgumentError(self, err_msg)

    return ErrorRaisingAction


# Definitions for some "types" to use with the arguments


def timespan(time_str) -> int:
    try:
        return parse_timespan(time_str)
    except ValueError as e:
        raise configargparse.ArgumentTypeError(str(e))


def positive_integer(string) -> int:
    try:
        value = int(string)
    except ValueError:
        raise configargparse.ArgumentTypeError(f"invalid int value: '{string}'")

    if value < 1:
        raise configargparse.ArgumentTypeError(
            f"Invalid --expect-workers argument ({value}), must be a positive number"
        )

    return value


def json_user_config(string):
    try:
        if string.endswith(".json"):
            with open(string) as file:
                user_config = json.load(file)