Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use PublishError along publishing #190

Closed

Conversation

MustafaJafar
Copy link
Contributor

@MustafaJafar MustafaJafar commented Dec 4, 2024

Changelog Description

resolve #108

This PR implements PublishError along the publish plugins.

  • RuntimeError
  • assert
  • KnownPublishError
  • Different type of Errors along publishing

Note

This PR shouldn't add PublishError to any functions in lib. instead, it should uses try..except.. in the caller code. More info #190 (comment)

Some Screenshots

image
image

Testing notes:

  1. Everything should still work as before
  2. Error messages related to the changes should be better.

@MustafaJafar MustafaJafar added the type: enhancement Improvement of existing functionality or minor addition label Dec 4, 2024
@MustafaJafar MustafaJafar self-assigned this Dec 4, 2024
@MustafaJafar MustafaJafar marked this pull request as draft December 4, 2024 16:18
@MustafaJafar MustafaJafar changed the title refactor RuntimeError to PublishError Use PublishError along publishing Dec 4, 2024
Comment on lines 49 to 52
if not isinstance(dest_data, dict):
raise PublishError(
message="Destination must be a dict."
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This provides way too little detail to be any meaningful error to any artist or alike. What destination where, for which key - and what did it get instead? We're really (I feel) going the wrong way if this can't just be a TypeError but requires a PublishError since we suddenly are introducing a super generic error much less clear? (I mean, still better than the assert, don't get me wrong)

@Illicit thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should every error (that can be raised along the publishing) be a PublishError ?
I've copula of scattered thoughts.

  • Any error that is not PublishError or PublishValidationError will cause the publisher UI to show the message (It's not your fault etc).
  • Some errors are originated from user interactions e.g. not selecting the correct node or using a wrong colorspace. I believe these definitely should be PublishError and PublishValidationError . These errors can be fixed by the user.
  • Other errors like the one you highlighted above, honestly, I don't know why/how it can happen and if the user has something to do with it. I assume it requires a developer to deal with them. but using PublishError can help developers know about the problem from a screenshot. (Note: I didn't use the title in the PublishError so the publish plugin's label will be used.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any error that is not PublishError or PublishValidationError will cause the publisher UI to show the message (It's not your fault etc).

Yup - this was a design decision at some point. I'm still not 100% confident that it's the right one, but it did force us into writing better PublishValidationError. If now we're just going to make EVERYTHING PublishError without providing better messages I think we're in the same problematic realm and we could basically revert to allow any error be nicely reported - we'll just still need to make sure that the majority of errors we raise are very clear what do to about them.

Some errors are originated from user interactions e.g. not selecting the correct node or using a wrong colorspace. I believe these definitely should be PublishError and PublishValidationError . These errors can be fixed by the user.

I can't think of any now - but that does sound right. However, the error must be very clear, describe what is wrong and how to go about fixing it, etc.

Other errors like the one you highlighted above, honestly, I don't know why/how it can happen and if the user has something to do with it. I assume it requires a developer to deal with them. but using PublishError can help developers know about the problem from a screenshot. (Note: I didn't use the title in the PublishError so the publish plugin's label will be used.)

Some assertions in the codebase were just there - to assert for a potential edge case where it might happen... not necessarily that they would happen. That's why some might not necessarily be bad to remain asserts (or other regular errors). They were just there because we just really wanted to make sure if the code continued that something behaved a certain way.

client/ayon_houdini/plugins/publish/save_scene.py Outdated Show resolved Hide resolved
@MustafaJafar
Copy link
Contributor Author

The function contains this line is used in imprint function which is used in publishing and loading.
Should we do something about it?

raise TypeError("Unsupported type: %r" % type(value))

@MustafaJafar MustafaJafar marked this pull request as ready for review December 4, 2024 22:57
def evalParmNoFrame(self, rop, parm, **kwargs):
try:
return evalParmNoFrame(rop, parm, **kwargs)
except Exception as exc:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I vaguely recall that hou.Error does not inherit from Exception - is that still the case? If so, we may need to capture hou.Error explicitly if the library function does not?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

evalParmNoFrame function has assert and RuntimeError and they'll be raised before the PublishError.
I don't know if that is sufficient.

client/ayon_houdini/api/lib.py Show resolved Hide resolved
client/ayon_houdini/plugins/publish/collect_usd_layers.py Outdated Show resolved Hide resolved
client/ayon_houdini/plugins/publish/collect_usd_render.py Outdated Show resolved Hide resolved
client/ayon_houdini/plugins/publish/extract_render.py Outdated Show resolved Hide resolved
try:
self.render_rop(instance)
except Exception as e:
import hou
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why import hou here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be able to call hou.node

Copy link
Member

@moonyuet moonyuet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good for me.

def get_output_parameter(self, node):
try:
return get_output_parameter(node)
except Exception as exc:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically we should only be capturing the TypeError here. Right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes. if the node.parm(...) didn't failed. and I think it won't fail.

client/ayon_houdini/api/plugin.py Outdated Show resolved Hide resolved
client/ayon_houdini/plugins/publish/collect_karma_rop.py Outdated Show resolved Hide resolved
Comment on lines 40 to 46
try:
render_products_data = ARenderProduct(aov_name)
except Exception as exc:
raise PublishError(
"Failed to get render products with colorspace.",
detail=f"{exc}"
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really doubt that raising these errors is an improvement over just letting it error. The raised errors tells me basically nothing about what caused it exactly and hence provides me as a developer nor as an artist the means to go solve it. Hence, the original error's exception must be (hopefully) clearer as to what is going on or failing.

I feel like our raised error is obfuscating the original error, no?

Also, note that you can do raise PublishError("message") from exc or raise PublishError("message").with_traceback(exc.__traceback__) although that's maybe a bit verbose. But I guess that's not raising an error in a way that looks nice in the Publisher UI.

What do we think @iLLiCiTiT @dee-ynput - are we obfuscating the errors and just making the code more complex or does this make sense? (Or should we instead still be changing how errors appear in the UI if NOT raised as PublishError so that a regular error occurring in code still looks better). I'm a bit worried we'll now be getting tons of PublishError("error occurred") like errors added to the code just to provide the stack trace in the end to the UI instead of 'keeping it away from artists'.

Are we battling our own UI decisions here?

Take a look at the changes in this PR - and what does it actually clarify to the raised errors, etc. whilst adding a lot more code for essentially raising the same error, but then as PublishError instead of the actual error that occurred.

Copy link
Member

@iLLiCiTiT iLLiCiTiT Dec 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PublishError is meant to tell artist "some information" why it crashed, so he knows why it failed (and maybe can fix it). I don't think all those errors that are re-raised as PublishError has value for artists. Some of them should stay as error as they're raised because of "code error", or the message should be more specific so artist do understand.

Example: f"Failed evaluating parameter '{parm}' on Rop node: {rop.path()}". Does this help artist in any way?

Also keep in mind that the original error (traceback) has some value for developers too...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For information, the current status of this PR aims to do the following:

  1. It raises publish errors instead of assert and other errors (from the caller functions in publish plugins).
  2. It shows the original error as detail in publish error.
  3. Enhance some error messages.

Personally I believe that PublishError should be used to guide the users about what could be wrong in their scene and how to fix it. e.g. missing frames -> tells the users to ensure that all frames exist

Maybe I abused it a little bit to capture the potential errors that could happen from the called functions so that they show up nicely.

Copy link
Member

@iLLiCiTiT iLLiCiTiT Dec 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PublishError

Shortly, it is issue that can be affected by artist or TD. It shows the message to artist that gives him a gist what happened and how he can potentially fix it or ask TD to fix it (e.g. via settings). We should write the information what he should do to fix it.
Made up examples:

  • "Deadline settings have missing, or invalid, credentials for 'http://some.url'."
  • "We don't support Maya 2022, please use 2023 or newer."
  • "Your model is not attached to camera but you requested review."
  • "Scene has set up multi-layer output, but AYON does not support."
  • "Valid ffmpeg executable is not available."

KnownPublishError

We know what happened it is some sort of a bug/unhandled case. Artist and TD should not care because it is error that cannot be affected by them at all.

  • "Project name is not set in 'projectName'. Could not initialize project's Anatomy."
  • "Missing AYON_PUBLISH_DATA environment variable."

Any unhandled error

We also might know they can happen, but it is better to have traceback. Same as with KnownPublishError, artist or TD should not care.

should be used to guide the users about what could be wrong in their scene and how to fix it. e.g. missing frames -> tells the users to ensure that all frames exist

Yes, but we should write what he should do, if the error does not tell it. Not just show error "missing frames" with exception message.

@MustafaJafar MustafaJafar marked this pull request as draft December 9, 2024 12:32
@MustafaJafar
Copy link
Contributor Author

closing in favor of #193

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement Improvement of existing functionality or minor addition
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Refactor RuntimeErrors to PublishErrors
4 participants