Giter Club home page Giter Club logo

starception's People

Contributors

alex-oleshkevich avatar dependabot[bot] avatar euri10 avatar jtraub avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

starception's Issues

python interpreter in browser debugger?

Any plans to include werkzeug-like python interpreter to starception? We use docker and fastapi in our work environment. There fore we cannot use vscode or pycharm debugger. It would be great if we can drop into Python intertpreter via browser if an exception occurs.

Incompatibility with starsessions

when using starsessions, excellent middleware btw :), there is a bug when trying to render the template, here is the trace

backend-1  | ERROR:    Exception in ASGI application
backend-1  | Traceback (most recent call last):
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/uvicorn/protocols/http/httptools_impl.py", line 401, in run_asgi
backend-1  |     result = await app(self.scope, self.receive, self.send)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
backend-1  |     return await self.app(scope, receive, send)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/uvicorn/middleware/message_logger.py", line 86, in __call__
backend-1  |     raise exc from None
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/uvicorn/middleware/message_logger.py", line 82, in __call__
backend-1  |     await self.app(scope, inner_receive, inner_send)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/fastapi/applications.py", line 269, in __call__
backend-1  |     await super().__call__(scope, receive, send)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starlette/applications.py", line 124, in __call__
backend-1  |     await self.middleware_stack(scope, receive, send)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starlette/middleware/errors.py", line 184, in __call__
backend-1  |     raise exc
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starlette/middleware/errors.py", line 162, in __call__
backend-1  |     await self.app(scope, receive, _send)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starsessions/middleware.py", line 86, in __call__
backend-1  |     await self.app(scope, receive, send_wrapper)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starception/middleware.py", line 44, in __call__
backend-1  |     response = self.debug_response(request, exc)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starception/middleware.py", line 57, in debug_response
backend-1  |     return exception_handler(request, exc)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starception/exception_handler.py", line 111, in exception_handler
backend-1  |     content = generate_html(request, exc)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starception/exception_handler.py", line 126, in generate_html
backend-1  |     return template.render(
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/jinja2/environment.py", line 1301, in render
backend-1  |     self.environment.handle_exception()
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/jinja2/environment.py", line 936, in handle_exception
backend-1  |     raise rewrite_traceback_stack(source=source)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starception/templates/index.html", line 41, in top-level template code
backend-1  |     {{ lib.details_row('Session', session) }}
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/jinja2/runtime.py", line 777, in _invoke
backend-1  |     rv = self._func(*arguments)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starception/templates/lib.html", line 4, in template
backend-1  |     {% for label, value in items|items %}
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/jinja2/filters.py", line 246, in do_items
backend-1  |     raise TypeError("Can only get item pairs from a mapping.")
backend-1  | TypeError: Can only get item pairs from a mapping.

the fix is simple and could happen here using request.session.data instead of request.session

'session': request.session if 'session' in request.scope else {},

but this wont be compatible with the default Starlette SessionMiddleware, so I'm not sure if this shouldn't be handled upstream in starsessions or if starception could detect the use of a custom middleware for sessions ;)

Minor html escaping issue

when an object has superior or inferior signs in its __repr__ the details_row macro if I get it right displays it "weirdly" :

an example, I have request.app.state._state["arqredis"] whose repr is ArqRedis<ConnectionPool<Connection<host=abdul_redis,port=6379,db=0>>>
and in the template it looks like the image below

20220811_1008_533x35_1660205300

AttributeError: 'NoneType' object has no attribute '__name__'

minmal reproducible example below

import json
import typing

import uvicorn
from asyncpg.pgproto.pgproto import UUID
from starlette.applications import Starlette
from starlette.middleware import Middleware
from starlette.requests import Request
from starlette.routing import Route

from starception import StarceptionMiddleware


class WithHintError(Exception):
    solution = (
        'The connection to the database cannot be established. '
        'Either the database server is down or connection credentials are invalid.'
    )


def index_view(request: Request) -> typing.NoReturn:
    uuid_dict = {"id": UUID('a4ccb480-e020-4f90-8951-ff859f731b40') }
    json.dumps(uuid_dict)


def hint_view(request: Request) -> typing.NoReturn:
    raise WithHintError('Oops, something really went wrong...')


app = Starlette(
    debug=True,
    routes=[Route('/', index_view), Route('/hint', hint_view)],
    middleware=[Middleware(StarceptionMiddleware)],
)

if __name__ == '__main__':
    uvicorn.run("starlette_app:app")

Should this become ASGI framework agnostic? Nearly there

Hi there,

This was flagged on florimondmanca/awesome-asgi#84 as a tool providing "amazing output in the developement phase". It surely looks so!

awesome-asgi is focused on tools and libraries that are as close to the ASGI spec as possible, i.e. "framework agnostic".

StarceptionMiddleware is already a pure ASGI middleware so it's already fairly agnostic.

From a quick analysis, it seems the only bit preventing this middleware from being usable with any ASGI framework is this line:

https://github.com/alex-oleshkevich/starception/blob/master/starception/middleware.py#L42

This would notably work with Starlette, which sets scope["app"] and exposes a .debug attribute. But this is not guaranteed to work for other frameworks if they don't comply with this interface (which will almost certainly be the case).

Maybe this middleware could keep the "automatic debug detection" functionality for Starlette-based framework, and rely on a debug=... parameter for other cases? Something like this...

class StarceptionMiddleware:
    def __init__(self, app, *, debug=None):
        self.app = app
        self._debug = debug

    async def __call__(self, scope, receive, send):
        ...

        try:
            debug = request.app.debug
        except AttributeError:
            if self._debug is None:
                raise RuntimeError(
                    "Could not infer whether the app is running in debug mode, as "
                    "'request.app.debug' is unavailable. "
                    "Hint: you can pass a debug flag explicitly using "
                    "'StarceptionMiddleware(app, debug=...)'."
                )
            debug = self._debug

Then, I believe the Integration with other frameworks documentation could hint at using StarceptionMiddleware(app, debug=...) instead of hinting users at using the exception_handler.

I believe that would work better because a) most (all?) of the ASGI frameworks have some middleware mounting API, but b) most frameworks that have an error handler API won't accept a Starlette Request instance.

Then I think the library would be fully framework-agnostic! On top of allowing support for the widest userbase possible, in my experience this also reduces the maintenance burden. Starlette can be hidden as an implementation detail, and not exposed in the library public API at all.

What do you think? I'll be happy to provide a PR.

secrets in url / db uri

what do you think of having url / uri keywords added to masked_secrets as they often contains passwords for redis, postgresql etc or maybe have an option to not display some added keywords

AttributeError: 'LoopContext' object has no attribute '_iterator'

greetings, wanted to try this with an asyncpg error I was debugging, the below raise an exception and I have the classical Starlette template outputing fine,

backend-1  | ERROR:    Exception in ASGI application
backend-1  | Traceback (most recent call last):
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/uvicorn/protocols/http/httptools_impl.py", line 401, in run_asgi
backend-1  |     result = await app(self.scope, self.receive, self.send)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
backend-1  |     return await self.app(scope, receive, send)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/uvicorn/middleware/message_logger.py", line 86, in __call__
backend-1  |     raise exc from None
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/uvicorn/middleware/message_logger.py", line 82, in __call__
backend-1  |     await self.app(scope, inner_receive, inner_send)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/fastapi/applications.py", line 269, in __call__
backend-1  |     await super().__call__(scope, receive, send)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starlette/applications.py", line 124, in __call__
backend-1  |     await self.middleware_stack(scope, receive, send)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starlette/middleware/errors.py", line 184, in __call__
backend-1  |     raise exc
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starlette/middleware/errors.py", line 162, in __call__
backend-1  |     await self.app(scope, receive, _send)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starsessions/middleware.py", line 86, in __call__
backend-1  |     await self.app(scope, receive, send_wrapper)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starlette/exceptions.py", line 93, in __call__
backend-1  |     raise exc
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starlette/exceptions.py", line 82, in __call__
backend-1  |     await self.app(scope, receive, sender)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py", line 21, in __call__
backend-1  |     raise e
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
backend-1  |     await self.app(scope, receive, send)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starlette/routing.py", line 670, in __call__
backend-1  |     await route.handle(scope, receive, send)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starlette/routing.py", line 266, in handle
backend-1  |     await self.app(scope, receive, send)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starlette/routing.py", line 65, in app
backend-1  |     response = await func(request)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/fastapi/routing.py", line 227, in app
backend-1  |     raw_response = await run_endpoint_function(
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/fastapi/routing.py", line 160, in run_endpoint_function
backend-1  |     return await dependant.call(**values)
backend-1  |   File "/opt/project/./abdul/routers/cart_router.py", line 110, in cart_get
backend-1  |     products, total_usd_decimal, total_xmr_decimal, order_now = await calculate_prices(
backend-1  |   File "/opt/project/./abdul/routers/cart_router.py", line 54, in calculate_prices
backend-1  |     xmr_price = await conn.fetchval_b(query_xmr_price, order_now=order_now)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/buildpg/asyncpg.py", line 69, in fetchval_b
backend-1  |     return await self.fetchval(query, *args, timeout=_timeout, column=_column)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/asyncpg/connection.py", line 645, in fetchval
backend-1  |     data = await self._execute(query, args, 1, timeout)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/asyncpg/connection.py", line 1659, in _execute
backend-1  |     result, _ = await self.__execute(
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/asyncpg/connection.py", line 1684, in __execute
backend-1  |     return await self._do_execute(
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/asyncpg/connection.py", line 1711, in _do_execute
backend-1  |     stmt = await self._get_statement(
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/asyncpg/connection.py", line 398, in _get_statement
backend-1  |     statement = await self._protocol.prepare(
backend-1  |   File "asyncpg/protocol/protocol.pyx", line 168, in prepare
backend-1  | asyncpg.exceptions.UndefinedFunctionError: operator does not exist: timestamp without time zone > interval
backend-1  | HINT:  No operator matches the given name and argument types. You might need to add explicit type casts.

but as soon as I add the middleware with app.add_middleware(StarceptionMiddleware, debug=True) I get no template and a Internal Server Error 500 page, and this error, not sure the issue is here or in Starlette itself though

backend-1  | ERROR:    Exception in ASGI application
backend-1  | Traceback (most recent call last):
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/uvicorn/protocols/http/httptools_impl.py", line 401, in run_asgi
backend-1  |     result = await app(self.scope, self.receive, self.send)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
backend-1  |     return await self.app(scope, receive, send)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/uvicorn/middleware/message_logger.py", line 86, in __call__
backend-1  |     raise exc from None
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/uvicorn/middleware/message_logger.py", line 82, in __call__
backend-1  |     await self.app(scope, inner_receive, inner_send)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/fastapi/applications.py", line 269, in __call__
backend-1  |     await super().__call__(scope, receive, send)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starlette/applications.py", line 124, in __call__
backend-1  |     await self.middleware_stack(scope, receive, send)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starlette/middleware/errors.py", line 167, in __call__
backend-1  |     response = self.debug_response(request, exc)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starlette/middleware/errors.py", line 248, in debug_response
backend-1  |     content = self.generate_html(exc)
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/starlette/middleware/errors.py", line 220, in generate_html
backend-1  |     traceback_obj = traceback.TracebackException.from_exception(
backend-1  |   File "/usr/local/lib/python3.10/traceback.py", line 572, in from_exception
backend-1  |     return cls(type(exc), exc, exc.__traceback__, *args, **kwargs)
backend-1  |   File "/usr/local/lib/python3.10/traceback.py", line 502, in __init__
backend-1  |     self.stack = StackSummary.extract(
backend-1  |   File "/usr/local/lib/python3.10/traceback.py", line 376, in extract
backend-1  |     result.append(FrameSummary(
backend-1  |   File "/usr/local/lib/python3.10/traceback.py", line 276, in __init__
backend-1  |     self.locals = {k: repr(v) for k, v in locals.items()} if locals else None
backend-1  |   File "/usr/local/lib/python3.10/traceback.py", line 276, in <dictcomp>
backend-1  |     self.locals = {k: repr(v) for k, v in locals.items()} if locals else None
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/jinja2/runtime.py", line 581, in __repr__
backend-1  |     return f"<{type(self).__name__} {self.index}/{self.length}>"
backend-1  |   File "/opt/venv/lib/python3.10/site-packages/jinja2/runtime.py", line 440, in length
backend-1  |     iterable = list(self._iterator)
backend-1  | AttributeError: 'LoopContext' object has no attribute '_iterator'
backend-1  | INFO:     172.20.0.1:60112 - "GET /cart/ HTTP/1.1" 500

Syntax highlighting in the browser

What if we do syntax highlighting in the browser? Starception already uses js to switch between frames so moving syntax highlighting to the client side is something that can be considered.

I am evaluating Highlight.js for this. A custom build can be created that contains just two themes and highlighters for selected languages (python, js, html, (s)css) and then integrated into Starception.

This would allow us to drop pygments dependency and use prefers-color-scheme media feature to automatically switch between light and dark themes. Lack of auto switching depending on day/night is the most irritating thing for me right now.

What are your thoughts @alex-oleshkevich ? Would you be willing to accept a PR with such change?

starception template broken if I have a typo using url_for

I think this should work, it's easily reproducible using url_for it seems

I have an endpoint that renders a template

If I make a mistake in the template on the line below (it should be order.conversations_uuid with an a and not converstions_uuid), then starception template is not correctly displayed (see screen)

<a href="{{ url_for("conversation_get", uuid=order.converstions_uuid ) }}">

20221107_1652_1908x1031_1667836369

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.