Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/run_tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Tests and Checks
on:
push:
branches: [master]
pull_request:
workflow_dispatch:
jobs:
build:
name: Run checks & tests
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14", "3.15-dev"]
runs-on: ${{ matrix.os }}
# Unreleased CPython breaks for reasons outside our control, so it warns
# instead of failing the build.
continue-on-error: ${{ endsWith(matrix.python-version, '-dev') }}
steps:
- uses: actions/checkout@v4
- name: Run ruff
uses: astral-sh/ruff-action@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .[testing]
- name: Run tests
run: |
pytest -v
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ dist/*
*.egg-info/*
.noseids
.idea
.pi-subagents/
3 changes: 0 additions & 3 deletions MANIFEST.in

This file was deleted.

14 changes: 11 additions & 3 deletions backlash/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
from backlash.debug import DebuggedApplication
from backlash.wsgi import WsgiDebuggedApplication
from backlash.asgi import AsgiDebuggedApplication
from backlash.debug import DebuggedApplication
from backlash.tracing.errors import TraceErrorsMiddleware
from backlash.tracing.slowrequests import TraceSlowRequestsMiddleware
from backlash.tracing.slowrequests import TraceSlowRequestsMiddleware
from backlash.wsgi import WsgiDebuggedApplication

__all__ = [
'DebuggedApplication',
'WsgiDebuggedApplication',
'AsgiDebuggedApplication',
'TraceErrorsMiddleware',
'TraceSlowRequestsMiddleware',
]
78 changes: 0 additions & 78 deletions backlash/_compat.py

This file was deleted.

1 change: 0 additions & 1 deletion backlash/asgi.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""ASGI shell of the interactive traceback debugger."""
import sys
from urllib.parse import parse_qs
Expand Down
32 changes: 15 additions & 17 deletions backlash/console.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""
werkzeug.debug.console
~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -8,18 +7,17 @@
:copyright: (c) 2011 by the Werkzeug Team, see AUTHORS for more details.
:license: BSD.
"""
import sys
import code
from types import CodeType
import sys
import threading
from types import CodeType

from backlash._compat import exec_, text_, binary_type
from backlash.utils import escape
from backlash.repr import debug_repr, dump, helper
from backlash.utils import escape

_local = threading.local()

class HTMLStringO(object):
class HTMLStringO:
"""A StringO version that HTML escapes on write."""

def __init__(self):
Expand Down Expand Up @@ -50,8 +48,8 @@ def reset(self):
return val

def _write(self, x):
if isinstance(x, binary_type):
x = text_(x, 'utf-8', 'replace')
if isinstance(x, bytes):
x = x.decode('utf-8', 'replace')
self._buffer.append(x)

def write(self, x):
Expand All @@ -61,23 +59,24 @@ def writelines(self, x):
self._write(escape(''.join(x)))


class ThreadedStream(object):
class ThreadedStream:
"""Thread-local wrapper for sys.stdout for the interactive console."""

@staticmethod
def push():
if not isinstance(sys.stdout, ThreadedStream):
sys.stdout = ThreadedStream()
_local.stream = HTMLStringO()
push = staticmethod(push)

@staticmethod
def fetch():
try:
stream = _local.stream
except AttributeError:
return ''
return stream.reset()
fetch = staticmethod(fetch)

@staticmethod
def displayhook(obj):
try:
stream = _local.stream
Expand All @@ -87,10 +86,9 @@ def displayhook(obj):
# already generating HTML for us.
if obj is not None:
stream._write(debug_repr(obj))
displayhook = staticmethod(displayhook)

def __setattr__(self, name, value):
raise AttributeError('read only attribute %s' % name)
raise AttributeError(f'read only attribute {name}')

def __dir__(self):
return dir(sys.__stdout__)
Expand All @@ -113,7 +111,7 @@ def __repr__(self):
sys.displayhook = ThreadedStream.displayhook


class _ConsoleLoader(object):
class _ConsoleLoader:

def __init__(self):
self._storage = {}
Expand Down Expand Up @@ -173,7 +171,7 @@ def runsource(self, source):

def runcode(self, code):
try:
exec_(code, self.globals, self.locals)
exec(code, self.globals, self.locals)
except Exception:
self.showtraceback()

Expand All @@ -191,7 +189,7 @@ def write(self, data):
sys.stdout.write(data)


class Console(object):
class Console:
"""An interactive console."""

def __init__(self, globals=None, locals=None, context=None):
Expand All @@ -204,7 +202,7 @@ def __init__(self, globals=None, locals=None, context=None):
def eval(self, code):
return self._ipy.runsource(code)

class _ConsoleFrame(object):
class _ConsoleFrame:
"""Helper class so that we can reuse the frame console code for the
standalone console.
"""
Expand Down
3 changes: 2 additions & 1 deletion backlash/debug.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# -*- coding: utf-8 -*-
"""Kept for backward compatibility only: the WSGI debugger historically
lived here as ``backlash.debug.DebuggedApplication``.

New code should use :class:`backlash.wsgi.WsgiDebuggedApplication` or
:class:`backlash.asgi.AsgiDebuggedApplication`.
"""
from backlash.wsgi import WsgiDebuggedApplication as DebuggedApplication

__all__ = ['DebuggedApplication']
11 changes: 5 additions & 6 deletions backlash/debugger.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""Transport-agnostic core of the interactive traceback debugger.

``DebuggerCore`` owns the debugger state (captured tracebacks, per-frame
Expand All @@ -10,18 +9,18 @@
adapt request parsing, response sending, and exception capture to their
transport.
"""
import mimetypes
import logging
from os.path import join, dirname, basename, isfile
import mimetypes
from os.path import basename, dirname, isfile, join

from backlash.tbtools import get_current_traceback, render_console_html
from backlash.console import Console
from backlash.tbtools import get_current_traceback, render_console_html
from backlash.utils import gen_salt

log = logging.getLogger('backlash')


class DebuggerCore(object):
class DebuggerCore:
"""State and endpoints shared by the WSGI and ASGI debugger middlewares.

:param app: the wrapped application (WSGI or ASGI, owned by the shell).
Expand Down Expand Up @@ -124,7 +123,7 @@ def get_resource(self, filename):
return 404, 'text/plain', b'Not Found'


class _ConsoleFrame(object):
class _ConsoleFrame:
"""Helper class so that we can reuse the frame console code for the
standalone console.
"""
Expand Down
6 changes: 4 additions & 2 deletions backlash/frtools.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import sys, inspect
from .tbtools import Traceback, Frame
import inspect
import sys

from .tbtools import Frame, Traceback


class DumpThread(Exception):
Expand Down
Loading
Loading