You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

76 line
3.0 KiB

  1. import os
  2. import mimetypes
  3. from sentry_sdk.envelope import Item, PayloadRef
  4. from typing import TYPE_CHECKING
  5. if TYPE_CHECKING:
  6. from typing import Optional, Union, Callable
  7. class Attachment:
  8. """Additional files/data to send along with an event.
  9. This class stores attachments that can be sent along with an event. Attachments are files or other data, e.g.
  10. config or log files, that are relevant to an event. Attachments are set on the ``Scope``, and are sent along with
  11. all non-transaction events (or all events including transactions if ``add_to_transactions`` is ``True``) that are
  12. captured within the ``Scope``.
  13. To add an attachment to a ``Scope``, use :py:meth:`sentry_sdk.Scope.add_attachment`. The parameters for
  14. ``add_attachment`` are the same as the parameters for this class's constructor.
  15. :param bytes: Raw bytes of the attachment, or a function that returns the raw bytes. Must be provided unless
  16. ``path`` is provided.
  17. :param filename: The filename of the attachment. Must be provided unless ``path`` is provided.
  18. :param path: Path to a file to attach. Must be provided unless ``bytes`` is provided.
  19. :param content_type: The content type of the attachment. If not provided, it will be guessed from the ``filename``
  20. parameter, if available, or the ``path`` parameter if ``filename`` is ``None``.
  21. :param add_to_transactions: Whether to add this attachment to transactions. Defaults to ``False``.
  22. """
  23. def __init__(
  24. self,
  25. bytes=None, # type: Union[None, bytes, Callable[[], bytes]]
  26. filename=None, # type: Optional[str]
  27. path=None, # type: Optional[str]
  28. content_type=None, # type: Optional[str]
  29. add_to_transactions=False, # type: bool
  30. ):
  31. # type: (...) -> None
  32. if bytes is None and path is None:
  33. raise TypeError("path or raw bytes required for attachment")
  34. if filename is None and path is not None:
  35. filename = os.path.basename(path)
  36. if filename is None:
  37. raise TypeError("filename is required for attachment")
  38. if content_type is None:
  39. content_type = mimetypes.guess_type(filename)[0]
  40. self.bytes = bytes
  41. self.filename = filename
  42. self.path = path
  43. self.content_type = content_type
  44. self.add_to_transactions = add_to_transactions
  45. def to_envelope_item(self):
  46. # type: () -> Item
  47. """Returns an envelope item for this attachment."""
  48. payload = None # type: Union[None, PayloadRef, bytes]
  49. if self.bytes is not None:
  50. if callable(self.bytes):
  51. payload = self.bytes()
  52. else:
  53. payload = self.bytes
  54. else:
  55. payload = PayloadRef(path=self.path)
  56. return Item(
  57. payload=payload,
  58. type="attachment",
  59. content_type=self.content_type,
  60. filename=self.filename,
  61. )
  62. def __repr__(self):
  63. # type: () -> str
  64. return "<Attachment %r>" % (self.filename,)