Skip to content

Instantly share code, notes, and snippets.

@martin-martin
Created September 1, 2022 14:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save martin-martin/cb7d7ad10ea42956d110d23309d18db8 to your computer and use it in GitHub Desktop.
Save martin-martin/cb7d7ad10ea42956d110d23309d18db8 to your computer and use it in GitHub Desktop.
Potential code for answering the question (errors bubble up)
# How can I make sure that the exception messages
# of Exceptions that occur in the sub-function `load_model()`
# show up in the stack trace of the `main()` function?
class UnsupportedInputError(Exception): pass
class SourceEqualsTargetError(Exception): pass
supported_inputs = ["a", "b", ...]
def load_model(source, target):
if source not in supported_inputs or target not in supported_inputs:
raise UnsupportedInputError("not supported pair")
elif source == target:
raise SourceEqualsTargetError("source and target shouldn't be same")
else: # Load the model
print("Loading model...")
model = "loaded model" # Replace with code logic
return model
def main(user_input):
model = load_model(user_input["source"], user_input["target"])
# try:
# model = load_model(user_input["source"], user_input["target"])
# except (UnsupportedInputError, SourceEqualsTargetError) as e:
# print(e)
# # return sys.exit(0) # Do you want to quit when theres an error?
# else: # Do something with the model
# print(model)
print("Run #1")
valid_input = {"source": "a", "target": "b"}
main(valid_input) # Should raise no error
print("Run #2")
invalid_input_1 = {"source": "a", "target": "a"}
main(invalid_input_1) # Should raise SourceEqualsTargetError
print("Run #3")
invalid_input_2 = {"source": "a", "target": "unsupported"}
main(invalid_input_2) # Should raise UnsupportedInputError
@martin-martin
Copy link
Author

@acsany I tried to reimagine the final code to keep more of the logic that the OP wanted to address and answer the question---so that the error messages actually bubble up without handling.

We could then do a final refactoring where we handle the errors in main() like shown in the commented-out bit of the code. Also seems like a close next step to create tests from our three test runs at the bottom, which would be a nice next step to point learners forward to.

What do you think?

@acsany
Copy link

acsany commented Sep 5, 2022

@martin-martin I really like the final code, especially with the (optional) addition of handling the error in main().

I also think that the three runs at the bottom are a great segway to mention additional resources about testing in the end. 👍

@acsany
Copy link

acsany commented Sep 5, 2022

For reference, we'll start the CoCo with the original code that the OH user posted:

# How can I make sure that the exception messages
# of Exceptions that occur in the sub-function `load_models`
# show up in the stack trace of the main function `predict_raw`?

supported = ['a', 'b', ...]

def load_model(source, target):
    try:
        if source == target:
            raise AssertionError("source and target shouldn't be same")
        if (source in supported) and (target in supported):
            ...
            if source == "ta":
                raise ValueError("Not supported pair")
    except AssertionError as e:
        return {"inputerror": "Please enter required fields"}
    except ValueError as e:
        return {"error": e}

# Assume this as flask API endpoint
def predict_raw(X):
    try:
        tokenizer, model = load_model(X['s'], X['t'])
        ...
        return preds
    except Exception as e:
        return {"error": e}

@martin-martin
Copy link
Author

Updated code based on inputs on Bandcamp:

# How can I make sure that the exception messages
# of Exceptions that occur in the sub-function `load_model()`
# show up in the stack trace of the `main()` function?


class UnsupportedPairError(Exception):
    pass


class SourceEqualsTargetError(Exception):
    pass


SUPPORTED_PARAMS = ["a", "b", ...]


def main(user_input):
    model = load_model(user_input["source"], user_input["target"])
    # try:
    #     model = load_model(user_input["source"], user_input["target"])
    # except (UnsupportedPairError, SourceEqualsTargetError) as e:
    #     print(e)
    #     # return sys.exit(0)  # Do you want to quit when theres an error?
    # else:  # Do something with the model
    #     print(model)


def validate(source, target, supported_params):
    if source not in supported_params or target not in supported_params:
        raise UnsupportedPairError("not supported pair")
    elif source == target:
        raise SourceEqualsTargetError("source and target shouldn't be same")


def load_model(source, target):
    validate(source, target, supported_params=SUPPORTED_PARAMS)
    print("Loading model...")
    model = "loaded model"  # Replace with code logic
    return model


print("Run #1")
valid_input = {"source": "a", "target": "b"}
main(valid_input)  # Should raise no error

print("Run #2")
invalid_input_1 = {"source": "a", "target": "a"}
main(invalid_input_1)  # Should raise SourceEqualsTargetError

print("Run #3")
invalid_input_2 = {"source": "a", "target": "unsupported"}
main(invalid_input_2)  # Should raise UnsupportedPairError

@martin-martin
Copy link
Author

What actually ended up being the final code:

# How can I make sure that the exception messages
# of Exceptions that occur in the sub-function `validate()`
# show up in the stack trace of the main function `main()`?


class SourceEqualsTargetError(Exception):
    """Source and target shouldn't be same."""


def main(user_input):
    try:
        validate(user_input["source"], user_input["target"])
    except SourceEqualsTargetError:
        print("Source and target are the same.")
    else:
        print("Done")


def validate(source, target):
    if source == target:
        raise SourceEqualsTargetError()


print("Run #1")
valid_input = {"source": 0, "target": 1}
main(valid_input)

print("Run #2")
invalid_input = {"source": 0, "target": 0}
main(invalid_input)

# Remove the `try...except` block in `validate()`.

@martin-martin
Copy link
Author

With an intermediate state to answer the question that looked like this:

# How can I make sure that the exception messages
# of Exceptions that occur in the sub-function `load_model()`
# show up in the stack trace of the main function `main()`?

def load_model(source, target):
    if source == target:
        raise AssertionError("source and target shouldn't be same")

def main(X):
    load_model(X['s'], X['t'])
    print("Done")

X = {"s": 0, "t": 0}
main(X)

# Remove the `try...except` block in `load_model()`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment