monkey_patches.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. __package__ = 'archivebox'
  2. import sys
  3. import shutil
  4. import django
  5. import pydantic
  6. import django_stubs_ext
  7. django_stubs_ext.monkeypatch()
  8. # monkey patch django timezone to add back utc (it was removed in Django 5.0)
  9. import datetime
  10. from django.utils import timezone
  11. timezone.utc = datetime.timezone.utc
  12. # monkey patch django-signals-webhooks to change how it shows up in Admin UI
  13. # from signal_webhooks.apps import DjangoSignalWebhooksConfig
  14. # DjangoSignalWebhooksConfig.verbose_name = 'API'
  15. # Install rich for pretty tracebacks in console logs
  16. # https://rich.readthedocs.io/en/stable/traceback.html#traceback-handler
  17. from rich.traceback import install # noqa
  18. TERM_WIDTH = (shutil.get_terminal_size((200, 10)).columns - 1) if sys.stdout.isatty() else 200
  19. # os.environ.setdefault('COLUMNS', str(TERM_WIDTH))
  20. install(show_locals=True, word_wrap=False, locals_max_length=10, locals_hide_dunder=True, suppress=[django, pydantic], extra_lines=2, width=TERM_WIDTH)
  21. # Hide site-packages/sonic/client.py:115: SyntaxWarning
  22. # https://github.com/xmonader/python-sonic-client/pull/18
  23. import warnings # noqa
  24. warnings.filterwarnings("ignore", category=SyntaxWarning, module='sonic')
  25. # Make daphne log requests quieter and esier to read
  26. from daphne import access # noqa
  27. class ModifiedAccessLogGenerator(access.AccessLogGenerator):
  28. """Clutge workaround until daphne uses the Python logging framework. https://github.com/django/daphne/pull/473/files"""
  29. def write_entry(self, host, date, request, status=None, length=None, ident=None, user=None):
  30. # Ignore noisy requests to staticfiles / favicons / etc.
  31. if 'GET /static/' in request:
  32. return
  33. if "GET /health/" in request:
  34. return
  35. if 'GET /admin/jsi18n/' in request:
  36. return
  37. if request.endswith("/favicon.ico") or request.endswith("/robots.txt") or request.endswith("/screenshot.png"):
  38. return
  39. if request.endswith('.css') or request.endswith('.js') or request.endswith('.woff') or request.endswith('.ttf'):
  40. return
  41. if str(status) in ('404', '304'):
  42. return
  43. # clean up the log format to mostly match the same format as django.conf.settings.LOGGING rich formats
  44. self.stream.write(
  45. "%s HTTP %s %s %s\n"
  46. % (
  47. date.strftime("%Y-%m-%d %H:%M:%S"),
  48. request,
  49. status or "-",
  50. "localhost" if host.startswith("127.") else host.split(":")[0],
  51. )
  52. )
  53. access.AccessLogGenerator.write_entry = ModifiedAccessLogGenerator.write_entry # type: ignore
  54. # fix benedict objects to pretty-print/repr more nicely with rich
  55. # https://stackoverflow.com/a/79048811/2156113
  56. # https://rich.readthedocs.io/en/stable/pretty.html#rich-repr-protocol
  57. import benedict # noqa
  58. benedict.benedict.__rich_repr__ = lambda self: (dict(self),) # type: ignore