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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add type annotations for exception #4681

Merged
merged 9 commits into from
May 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 10 additions & 1 deletion lib/streamlit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,17 @@ def experimental_show(*args):
markdown("**%s**" % escaped)
write(args[idx])

except Exception:
except Exception as raised_exc:
_, exc, exc_tb = _sys.exc_info()
if exc is None:
# Presumably, exc should never be None, but it is typed as
# Optional, and I don't know the internals of sys.exc_info() well
# enough to just use a cast here. Hence, the runtime check.
raise RuntimeError(
"Unexpected state: exc was None. If you see this message, "
"please create an issue at "
"https://github.com/streamlit/streamlit/issues"
) from raised_exc
exception(exc)


Expand Down
33 changes: 18 additions & 15 deletions lib/streamlit/elements/exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@

import os
import traceback
import typing
from typing import Optional, cast, List
from typing import cast, List, Optional, TYPE_CHECKING
from typing_extensions import Final

import streamlit
from streamlit.proto.Exception_pb2 import Exception as ExceptionProto
Expand All @@ -26,22 +26,24 @@
from streamlit.errors import UncaughtAppException
from streamlit.logger import get_logger

LOGGER = get_logger(__name__)
if TYPE_CHECKING:
from streamlit.delta_generator import DeltaGenerator

LOGGER: Final = get_logger(__name__)

# When client.showErrorDetails is False, we show a generic warning in the
# frontend when we encounter an uncaught app exception.
_GENERIC_UNCAUGHT_EXCEPTION_TEXT = "This app has encountered an error. The original error message is redacted to prevent data leaks. Full error details have been recorded in the logs (if you're on Streamlit Cloud, click on 'Manage app' in the lower right of your app)."

# Extract the streamlit package path
_STREAMLIT_DIR = os.path.dirname(streamlit.__file__)
_GENERIC_UNCAUGHT_EXCEPTION_TEXT: Final = "This app has encountered an error. The original error message is redacted to prevent data leaks. Full error details have been recorded in the logs (if you're on Streamlit Cloud, click on 'Manage app' in the lower right of your app)."

# Make it absolute, resolve aliases, and ensure there's a trailing path
# separator
_STREAMLIT_DIR = os.path.join(os.path.realpath(_STREAMLIT_DIR), "")
# Extract the streamlit package path. Make it absolute, resolve aliases, and
# ensure there's a trailing path separator
_STREAMLIT_DIR: Final = os.path.join(
os.path.realpath(os.path.dirname(streamlit.__file__)), ""
)


class ExceptionMixin:
def exception(self, exception):
def exception(self, exception: BaseException) -> "DeltaGenerator":
"""Display an exception.

Parameters
Expand All @@ -57,12 +59,13 @@ def exception(self, exception):
"""
exception_proto = ExceptionProto()
marshall(exception_proto, exception)
return self.dg._enqueue("exception", exception_proto)
dg = self.dg._enqueue("exception", exception_proto)
return cast("DeltaGenerator", dg)

@property
def dg(self) -> "streamlit.delta_generator.DeltaGenerator":
def dg(self) -> "DeltaGenerator":
"""Get our DeltaGenerator."""
return cast("streamlit.delta_generator.DeltaGenerator", self)
return cast("DeltaGenerator", self)


def marshall(exception_proto: ExceptionProto, exception: BaseException) -> None:
Expand Down Expand Up @@ -140,7 +143,7 @@ def marshall(exception_proto: ExceptionProto, exception: BaseException) -> None:
)

if is_uncaught_app_exception:
uae = typing.cast(UncaughtAppException, exception)
uae = cast(UncaughtAppException, exception)
exception_proto.message = _GENERIC_UNCAUGHT_EXCEPTION_TEXT
type_str = str(type(uae.exc))
exception_proto.type = type_str.replace("<class '", "").replace("'>", "")
Expand Down