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

Unclear error message when a custom version source raises an exception type which can't be constructed #959

Open
object-Object opened this issue Sep 5, 2023 · 1 comment

Comments

@object-Object
Copy link
Contributor

Fairly minimal reproducible example: https://gist.github.com/object-Object/e981b4a717f716914e3d02ab4d5258d2

I encountered this issue with Pydantic, whose ValidationError exception doesn't have a constructor. ValidationError is implemented in Rust via PyO3, and when a class without a constructor is initialized, the exception raised by PyO3 seems to behave like raise ... from None.

Hatchling apparently uses the following code to invoke a custom version source:

try:
self._cached = self.source.get_version_data()['version']
except Exception as e:
message = f'Error getting the version from source `{self.source.PLUGIN_NAME}`: {e}'
raise type(e)(message) from None

If the constructor of type(e) raises an exception using from None or equivalent, e is never displayed to the user. For example, from the above gist:

Traceback (most recent call last):
  File "C:\Users\redacted\hatch-bug\venv\Lib\site-packages\pyproject_hooks\_in_process\_in_process.py", line 353, in <module>
    main()
  File "C:\Users\redacted\hatch-bug\venv\Lib\site-packages\pyproject_hooks\_in_process\_in_process.py", line 335, in main
    json_out['return_val'] = hook(**hook_input['kwargs'])
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\redacted\hatch-bug\venv\Lib\site-packages\pyproject_hooks\_in_process\_in_process.py", line 304, in build_sdist
    return backend.build_sdist(sdist_directory, config_settings)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\redacted\AppData\Local\Temp\build-env-1s5k16uu\Lib\site-packages\hatchling\build.py", line 34, in build_sdist
    return os.path.basename(next(builder.build(sdist_directory, ['standard'])))
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\redacted\AppData\Local\Temp\build-env-1s5k16uu\Lib\site-packages\hatchling\builders\plugin\interface.py", line 93, in build  
    self.metadata.validate_fields()
  File "C:\Users\redacted\AppData\Local\Temp\build-env-1s5k16uu\Lib\site-packages\hatchling\metadata\core.py", line 243, in validate_fields   
    _ = self.version
        ^^^^^^^^^^^^
  File "C:\Users\redacted\AppData\Local\Temp\build-env-1s5k16uu\Lib\site-packages\hatchling\metadata\core.py", line 128, in version
    self._version = self._get_version()
                    ^^^^^^^^^^^^^^^^^^^
  File "C:\Users\redacted\AppData\Local\Temp\build-env-1s5k16uu\Lib\site-packages\hatchling\metadata\core.py", line 226, in _get_version      
    version = self.hatch.version.cached
              ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\redacted\AppData\Local\Temp\build-env-1s5k16uu\Lib\site-packages\hatchling\metadata\core.py", line 1415, in cached
    raise type(e)(message) from None
          ^^^^^^^^^^^^^^^^
  File "C:\Users\redacted\AppData\Local\Temp\build-env-1s5k16uu\Lib\site-packages\hatch_plugin.py", line 9, in __new__
    raise TypeError("This hides the real error message") from None
TypeError: This hides the real error message

I do think this would also be considered a bug in Pydantic and PyO3, but it wouldn't have been triggered if Hatchling didn't try to re-construct the exception.

A simple fix might be to use eg. raise RuntimeError(message) from e instead of trying to construct another instance of the original error.

@object-Object
Copy link
Contributor Author

On second thought, I think Pydantic's ValidationError is actually entirely valid, since subclasses' constructors are allowed to take different arguments than their parents' (see also: why this is valid under the LSP). So the pattern type(e)(message) is probably not a good idea anyway. It's just more of an issue here because PyO3 is swallowing the exception context so we can't see the original error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant