Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-sentry-sdk for 
openSUSE:Factory checked in at 2021-11-20 02:39:16
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-sentry-sdk (Old)
 and      /work/SRC/openSUSE:Factory/.python-sentry-sdk.new.1895 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-sentry-sdk"

Sat Nov 20 02:39:16 2021 rev:18 rq:932485 version:1.5.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-sentry-sdk/python-sentry-sdk.changes      
2021-10-27 22:21:34.715210129 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-sentry-sdk.new.1895/python-sentry-sdk.changes
    2021-11-20 02:40:28.592515576 +0100
@@ -1,0 +2,13 @@
+Fri Nov 19 08:41:01 UTC 2021 - ecsos <ec...@opensuse.org>
+
+- Update to 1.5.0
+  - Also record client outcomes for before send #1211
+  - Add support for implicitly sized envelope items #1229
+  - Fix integration with Apache Beam 2.32, 2.33 #1233
+  - Remove Python 2.7 support for AWS Lambda layers in craft config #1241
+  - Refactor Sanic integration for v21.9 support #1212
+  - AWS Lambda Python 3.9 runtime support #1239
+  - Fix "shutdown_timeout" typing #1256
+- Disable of python36 build, because out of support at 2021-12-23.
+
+-------------------------------------------------------------------

Old:
----
  sentry-python-1.4.1.tar.gz

New:
----
  sentry-python-1.5.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-sentry-sdk.spec ++++++
--- /var/tmp/diff_new_pack.EX7pwz/_old  2021-11-20 02:40:29.052514058 +0100
+++ /var/tmp/diff_new_pack.EX7pwz/_new  2021-11-20 02:40:29.056514045 +0100
@@ -19,8 +19,9 @@
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 # nothing provides python2-venusian >= 1.0 needed by python2-pyramid
 %define skip_python2 1
+%define skip_python36 1
 Name:           python-sentry-sdk
-Version:        1.4.1
+Version:        1.5.0
 Release:        0
 Summary:        Python SDK for Sentry.io
 License:        BSD-2-Clause
@@ -37,10 +38,11 @@
 BuildRequires:  %{python_module certifi}
 BuildRequires:  %{python_module executing}
 BuildRequires:  %{python_module falcon >= 1.4}
+BuildRequires:  %{python_module httpx >= 0.16.0}
 BuildRequires:  %{python_module rq >= 0.6}
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  %{python_module tornado >= 5}
-BuildRequires:  %{python_module urllib3}
+BuildRequires:  %{python_module urllib3 >= 1.10.0}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
 # SECTION test requirements
@@ -50,7 +52,7 @@
 BuildRequires:  %{python_module hypothesis}
 BuildRequires:  %{python_module jsonschema >= 3.2.0}
 BuildRequires:  %{python_module pyramid}
-BuildRequires:  %{python_module pyrsistent}
+BuildRequires:  %{python_module pyrsistent >= 0.16.0}
 BuildRequires:  %{python_module pytest-cov >= 2.8.1}
 BuildRequires:  %{python_module pytest-forked >= 1.1.3}
 BuildRequires:  %{python_module pytest-localserver >= 0.5.0}
@@ -75,10 +77,11 @@
 Requires:       python-certifi
 Requires:       python-executing
 Requires:       python-falcon >= 1.4
+Requires:       python-httpx >= 0.16.0
 Requires:       python-jsonschema
 Requires:       python-rq >= 0.6
 Requires:       python-tornado >= 5
-Requires:       python-urllib3
+Requires:       python-urllib3 >= 1.10.0
 # SECTION extra requirements - which rise up buildtime error or missing in 
openSUSE
 #Requires:       python-Django >= 1.8
 #Requires:       python-sanic >= 0.8

++++++ sentry-python-1.4.1.tar.gz -> sentry-python-1.5.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sentry-python-1.4.1/.craft.yml 
new/sentry-python-1.5.0/.craft.yml
--- old/sentry-python-1.4.1/.craft.yml  2021-09-22 14:34:25.000000000 +0200
+++ new/sentry-python-1.5.0/.craft.yml  2021-11-16 19:57:37.000000000 +0100
@@ -18,10 +18,10 @@
         # On the other hand, AWS Lambda does not support every Python runtime.
         # The supported runtimes are available in the following link:
         # https://docs.aws.amazon.com/lambda/latest/dg/lambda-python.html
-          - python2.7
           - python3.6
           - python3.7
           - python3.8
+          - python3.9
     license: MIT
 changelog: CHANGELOG.md
 changelogPolicy: simple
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sentry-python-1.4.1/CHANGELOG.md 
new/sentry-python-1.5.0/CHANGELOG.md
--- old/sentry-python-1.4.1/CHANGELOG.md        2021-09-22 14:34:25.000000000 
+0200
+++ new/sentry-python-1.5.0/CHANGELOG.md        2021-11-16 19:57:37.000000000 
+0100
@@ -22,7 +22,25 @@
 
 ## Unreleased
 
-- TBA
+## 1.5.0
+
+- Also record client outcomes for before send #1211
+- Add support for implicitly sized envelope items #1229
+- Fix integration with Apache Beam 2.32, 2.33 #1233
+- Remove Python 2.7 support for AWS Lambda layers in craft config #1241
+- Refactor Sanic integration for v21.9 support #1212
+- AWS Lambda Python 3.9 runtime support #1239
+- Fix "shutdown_timeout" typing #1256
+
+Work in this release contributed by @galuszkak, @kianmeng, @ahopkins, 
@razumeiko, @tomscytale, and @seedofjoy. Thank you for your contribution!
+
+## 1.4.3
+
+- Turned client reports on by default.
+
+## 1.4.2
+
+- Made envelope modifications in the HTTP transport non observable #1206
 
 ## 1.4.1
 
@@ -46,7 +64,7 @@
 ## 1.2.0
 
 - Fix for `AWSLambda` Integration to handle other path formats for function 
initial handler #1139
-- Fix for worker to set deamon attribute instead of deprecated setDaemon 
method #1093
+- Fix for worker to set daemon attribute instead of deprecated setDaemon 
method #1093
 - Fix for `bottle` Integration that discards `-dev` for version extraction 
#1085
 - Fix for transport that adds a unified hook for capturing metrics about 
dropped events #1100
 - Add `Httpx` Integration #1119
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sentry-python-1.4.1/docs/conf.py 
new/sentry-python-1.5.0/docs/conf.py
--- old/sentry-python-1.4.1/docs/conf.py        2021-09-22 14:34:25.000000000 
+0200
+++ new/sentry-python-1.5.0/docs/conf.py        2021-11-16 19:57:37.000000000 
+0100
@@ -29,7 +29,7 @@
 copyright = u"2019, Sentry Team and Contributors"
 author = u"Sentry Team and Contributors"
 
-release = "1.4.1"
+release = "1.5.0"
 version = ".".join(release.split(".")[:2])  # The short X.Y version.
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sentry-python-1.4.1/sentry_sdk/client.py 
new/sentry-python-1.5.0/sentry_sdk/client.py
--- old/sentry-python-1.4.1/sentry_sdk/client.py        2021-09-22 
14:34:25.000000000 +0200
+++ new/sentry-python-1.5.0/sentry_sdk/client.py        2021-11-16 
19:57:37.000000000 +0100
@@ -201,6 +201,10 @@
                 new_event = before_send(event, hint or {})
             if new_event is None:
                 logger.info("before send dropped event (%s)", event)
+                if self.transport:
+                    self.transport.record_lost_event(
+                        "before_send", data_category="error"
+                    )
             event = new_event  # type: ignore
 
         return event
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sentry-python-1.4.1/sentry_sdk/consts.py 
new/sentry-python-1.5.0/sentry_sdk/consts.py
--- old/sentry-python-1.4.1/sentry_sdk/consts.py        2021-09-22 
14:34:25.000000000 +0200
+++ new/sentry-python-1.5.0/sentry_sdk/consts.py        2021-11-16 
19:57:37.000000000 +0100
@@ -52,7 +52,7 @@
         release=None,  # type: Optional[str]
         environment=None,  # type: Optional[str]
         server_name=None,  # type: Optional[str]
-        shutdown_timeout=2,  # type: int
+        shutdown_timeout=2,  # type: float
         integrations=[],  # type: Sequence[Integration]  # noqa: B006
         in_app_include=[],  # type: List[str]  # noqa: B006
         in_app_exclude=[],  # type: List[str]  # noqa: B006
@@ -76,7 +76,7 @@
         traces_sampler=None,  # type: Optional[TracesSampler]
         auto_enabling_integrations=True,  # type: bool
         auto_session_tracking=True,  # type: bool
-        send_client_reports=False,  # type: bool
+        send_client_reports=True,  # type: bool
         _experiments={},  # type: Experiments  # noqa: B006
     ):
         # type: (...) -> None
@@ -101,7 +101,7 @@
 del _get_default_options
 
 
-VERSION = "1.4.1"
+VERSION = "1.5.0"
 SDK_INFO = {
     "name": "sentry.python",
     "version": VERSION,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sentry-python-1.4.1/sentry_sdk/envelope.py 
new/sentry-python-1.5.0/sentry_sdk/envelope.py
--- old/sentry-python-1.4.1/sentry_sdk/envelope.py      2021-09-22 
14:34:25.000000000 +0200
+++ new/sentry-python-1.5.0/sentry_sdk/envelope.py      2021-11-16 
19:57:37.000000000 +0100
@@ -295,13 +295,18 @@
         if not line:
             return None
         headers = parse_json(line)
-        length = headers["length"]
-        payload = f.read(length)
-        if headers.get("type") in ("event", "transaction"):
+        length = headers.get("length")
+        if length is not None:
+            payload = f.read(length)
+            f.readline()
+        else:
+            # if no length was specified we need to read up to the end of line
+            # and remove it (if it is present, i.e. not the very last char in 
an eof terminated envelope)
+            payload = f.readline().rstrip(b"\n")
+        if headers.get("type") in ("event", "transaction", "metric_buckets"):
             rv = cls(headers=headers, 
payload=PayloadRef(json=parse_json(payload)))
         else:
             rv = cls(headers=headers, payload=payload)
-        f.readline()
         return rv
 
     @classmethod
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/sentry-python-1.4.1/sentry_sdk/integrations/aiohttp.py 
new/sentry-python-1.5.0/sentry_sdk/integrations/aiohttp.py
--- old/sentry-python-1.4.1/sentry_sdk/integrations/aiohttp.py  2021-09-22 
14:34:25.000000000 +0200
+++ new/sentry-python-1.5.0/sentry_sdk/integrations/aiohttp.py  2021-11-16 
19:57:37.000000000 +0100
@@ -65,9 +65,7 @@
         try:
             version = tuple(map(int, AIOHTTP_VERSION.split(".")[:2]))
         except (TypeError, ValueError):
-            raise DidNotEnable(
-                "AIOHTTP version unparseable: {}".format(AIOHTTP_VERSION)
-            )
+            raise DidNotEnable("AIOHTTP version unparsable: 
{}".format(AIOHTTP_VERSION))
 
         if version < (3, 4):
             raise DidNotEnable("AIOHTTP 3.4 or newer required.")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/sentry-python-1.4.1/sentry_sdk/integrations/aws_lambda.py 
new/sentry-python-1.5.0/sentry_sdk/integrations/aws_lambda.py
--- old/sentry-python-1.4.1/sentry_sdk/integrations/aws_lambda.py       
2021-09-22 14:34:25.000000000 +0200
+++ new/sentry-python-1.5.0/sentry_sdk/integrations/aws_lambda.py       
2021-11-16 19:57:37.000000000 +0100
@@ -284,12 +284,14 @@
     # Python 3.7: If the bootstrap module is *already imported*, it is the
     # one we actually want to use (no idea what's in __main__)
     #
-    # On Python 3.8 bootstrap is also importable, but will be the same file
+    # Python 3.8: bootstrap is also importable, but will be the same file
     # as __main__ imported under a different name:
     #
     #     sys.modules['__main__'].__file__ == sys.modules['bootstrap'].__file__
     #     sys.modules['__main__'] is not sys.modules['bootstrap']
     #
+    # Python 3.9: bootstrap is in __main__.awslambdaricmain
+    #
     # On container builds using the 
`aws-lambda-python-runtime-interface-client`
     # (awslamdaric) module, bootstrap is located in 
sys.modules['__main__'].bootstrap
     #
@@ -297,10 +299,18 @@
     if "bootstrap" in sys.modules:
         return sys.modules["bootstrap"]
     elif "__main__" in sys.modules:
-        if hasattr(sys.modules["__main__"], "bootstrap"):
+        module = sys.modules["__main__"]
+        # python3.9 runtime
+        if hasattr(module, "awslambdaricmain") and hasattr(
+            module.awslambdaricmain, "bootstrap"  # type: ignore
+        ):
+            return module.awslambdaricmain.bootstrap  # type: ignore
+        elif hasattr(module, "bootstrap"):
             # awslambdaric python module in container builds
-            return sys.modules["__main__"].bootstrap  # type: ignore
-        return sys.modules["__main__"]
+            return module.bootstrap  # type: ignore
+
+        # python3.8 runtime
+        return module
     else:
         return None
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sentry-python-1.4.1/sentry_sdk/integrations/beam.py 
new/sentry-python-1.5.0/sentry_sdk/integrations/beam.py
--- old/sentry-python-1.4.1/sentry_sdk/integrations/beam.py     2021-09-22 
14:34:25.000000000 +0200
+++ new/sentry-python-1.5.0/sentry_sdk/integrations/beam.py     2021-11-16 
19:57:37.000000000 +0100
@@ -80,7 +80,6 @@
 
 def _wrap_inspect_call(cls, func_name):
     # type: (Any, Any) -> Any
-    from apache_beam.typehints.decorators import getfullargspec  # type: ignore
 
     if not hasattr(cls, func_name):
         return None
@@ -105,6 +104,8 @@
 
             return get_function_args_defaults(process_func)
         except ImportError:
+            from apache_beam.typehints.decorators import getfullargspec  # 
type: ignore
+
             return getfullargspec(process_func)
 
     setattr(_inspect, USED_FUNC, True)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sentry-python-1.4.1/sentry_sdk/integrations/sanic.py 
new/sentry-python-1.5.0/sentry_sdk/integrations/sanic.py
--- old/sentry-python-1.4.1/sentry_sdk/integrations/sanic.py    2021-09-22 
14:34:25.000000000 +0200
+++ new/sentry-python-1.5.0/sentry_sdk/integrations/sanic.py    2021-11-16 
19:57:37.000000000 +0100
@@ -27,6 +27,7 @@
     from sanic.request import Request, RequestParameters
 
     from sentry_sdk._types import Event, EventProcessor, Hint
+    from sanic.router import Route
 
 try:
     from sanic import Sanic, __version__ as SANIC_VERSION
@@ -36,19 +37,31 @@
 except ImportError:
     raise DidNotEnable("Sanic not installed")
 
+old_error_handler_lookup = ErrorHandler.lookup
+old_handle_request = Sanic.handle_request
+old_router_get = Router.get
+
+try:
+    # This method was introduced in Sanic v21.9
+    old_startup = Sanic._startup
+except AttributeError:
+    pass
+
 
 class SanicIntegration(Integration):
     identifier = "sanic"
+    version = (0, 0)  # type: Tuple[int, ...]
 
     @staticmethod
     def setup_once():
         # type: () -> None
+
         try:
-            version = tuple(map(int, SANIC_VERSION.split(".")))
+            SanicIntegration.version = tuple(map(int, 
SANIC_VERSION.split(".")))
         except (TypeError, ValueError):
             raise DidNotEnable("Unparsable Sanic version: 
{}".format(SANIC_VERSION))
 
-        if version < (0, 8):
+        if SanicIntegration.version < (0, 8):
             raise DidNotEnable("Sanic 0.8 or newer required.")
 
         if not HAS_REAL_CONTEXTVARS:
@@ -71,89 +84,194 @@
             # https://github.com/huge-success/sanic/issues/1332
             ignore_logger("root")
 
-        old_handle_request = Sanic.handle_request
+        if SanicIntegration.version < (21, 9):
+            _setup_legacy_sanic()
+            return
 
-        async def sentry_handle_request(self, request, *args, **kwargs):
-            # type: (Any, Request, *Any, **Any) -> Any
-            hub = Hub.current
-            if hub.get_integration(SanicIntegration) is None:
-                return old_handle_request(self, request, *args, **kwargs)
-
-            weak_request = weakref.ref(request)
-
-            with Hub(hub) as hub:
-                with hub.configure_scope() as scope:
-                    scope.clear_breadcrumbs()
-                    
scope.add_event_processor(_make_request_processor(weak_request))
-
-                response = old_handle_request(self, request, *args, **kwargs)
-                if isawaitable(response):
-                    response = await response
-
-                return response
-
-        Sanic.handle_request = sentry_handle_request
-
-        old_router_get = Router.get
-
-        def sentry_router_get(self, *args):
-            # type: (Any, Union[Any, Request]) -> Any
-            rv = old_router_get(self, *args)
-            hub = Hub.current
-            if hub.get_integration(SanicIntegration) is not None:
-                with capture_internal_exceptions():
-                    with hub.configure_scope() as scope:
-                        if version >= (21, 3):
-                            # Sanic versions above and including 21.3 append 
the app name to the
-                            # route name, and so we need to remove it from 
Route name so the
-                            # transaction name is consistent across all 
versions
-                            sanic_app_name = self.ctx.app.name
-                            sanic_route = rv[0].name
-
-                            if sanic_route.startswith("%s." % sanic_app_name):
-                                # We add a 1 to the len of the sanic_app_name 
because there is a dot
-                                # that joins app name and the route name
-                                # Format: app_name.route_name
-                                sanic_route = sanic_route[len(sanic_app_name) 
+ 1 :]
-
-                            scope.transaction = sanic_route
-                        else:
-                            scope.transaction = rv[0].__name__
-            return rv
-
-        Router.get = sentry_router_get
-
-        old_error_handler_lookup = ErrorHandler.lookup
-
-        def sentry_error_handler_lookup(self, exception):
-            # type: (Any, Exception) -> Optional[object]
-            _capture_exception(exception)
-            old_error_handler = old_error_handler_lookup(self, exception)
+        _setup_sanic()
 
-            if old_error_handler is None:
-                return None
 
-            if Hub.current.get_integration(SanicIntegration) is None:
-                return old_error_handler
+class SanicRequestExtractor(RequestExtractor):
+    def content_length(self):
+        # type: () -> int
+        if self.request.body is None:
+            return 0
+        return len(self.request.body)
+
+    def cookies(self):
+        # type: () -> Dict[str, str]
+        return dict(self.request.cookies)
+
+    def raw_data(self):
+        # type: () -> bytes
+        return self.request.body
+
+    def form(self):
+        # type: () -> RequestParameters
+        return self.request.form
+
+    def is_json(self):
+        # type: () -> bool
+        raise NotImplementedError()
+
+    def json(self):
+        # type: () -> Optional[Any]
+        return self.request.json
+
+    def files(self):
+        # type: () -> RequestParameters
+        return self.request.files
+
+    def size_of_file(self, file):
+        # type: (Any) -> int
+        return len(file.body or ())
+
+
+def _setup_sanic():
+    # type: () -> None
+    Sanic._startup = _startup
+    ErrorHandler.lookup = _sentry_error_handler_lookup
+
+
+def _setup_legacy_sanic():
+    # type: () -> None
+    Sanic.handle_request = _legacy_handle_request
+    Router.get = _legacy_router_get
+    ErrorHandler.lookup = _sentry_error_handler_lookup
+
+
+async def _startup(self):
+    # type: (Sanic) -> None
+    # This happens about as early in the lifecycle as possible, just after the
+    # Request object is created. The body has not yet been consumed.
+    self.signal("http.lifecycle.request")(_hub_enter)
+
+    # This happens after the handler is complete. In v21.9 this signal is not
+    # dispatched when there is an exception. Therefore we need to close out
+    # and call _hub_exit from the custom exception handler as well.
+    # See https://github.com/sanic-org/sanic/issues/2297
+    self.signal("http.lifecycle.response")(_hub_exit)
+
+    # This happens inside of request handling immediately after the route
+    # has been identified by the router.
+    self.signal("http.routing.after")(_set_transaction)
+
+    # The above signals need to be declared before this can be called.
+    await old_startup(self)
+
+
+async def _hub_enter(request):
+    # type: (Request) -> None
+    hub = Hub.current
+    request.ctx._sentry_do_integration = (
+        hub.get_integration(SanicIntegration) is not None
+    )
+
+    if not request.ctx._sentry_do_integration:
+        return
+
+    weak_request = weakref.ref(request)
+    request.ctx._sentry_hub = Hub(hub)
+    request.ctx._sentry_hub.__enter__()
+
+    with request.ctx._sentry_hub.configure_scope() as scope:
+        scope.clear_breadcrumbs()
+        scope.add_event_processor(_make_request_processor(weak_request))
+
 
-            async def sentry_wrapped_error_handler(request, exception):
-                # type: (Request, Exception) -> Any
-                try:
-                    response = old_error_handler(request, exception)
-                    if isawaitable(response):
-                        response = await response
-                    return response
-                except Exception:
-                    # Report errors that occur in Sanic error handler. These
-                    # exceptions will not even show up in Sanic's
-                    # `sanic.exceptions` logger.
-                    exc_info = sys.exc_info()
-                    _capture_exception(exc_info)
-                    reraise(*exc_info)
+async def _hub_exit(request, **_):
+    # type: (Request, **Any) -> None
+    request.ctx._sentry_hub.__exit__(None, None, None)
 
-            return sentry_wrapped_error_handler
 
-        ErrorHandler.lookup = sentry_error_handler_lookup
+async def _set_transaction(request, route, **kwargs):
+    # type: (Request, Route, **Any) -> None
+    hub = Hub.current
+    if hub.get_integration(SanicIntegration) is not None:
+        with capture_internal_exceptions():
+            with hub.configure_scope() as scope:
+                route_name = route.name.replace(request.app.name, 
"").strip(".")
+                scope.transaction = route_name
+
+
+def _sentry_error_handler_lookup(self, exception, *args, **kwargs):
+    # type: (Any, Exception, *Any, **Any) -> Optional[object]
+    _capture_exception(exception)
+    old_error_handler = old_error_handler_lookup(self, exception, *args, 
**kwargs)
+
+    if old_error_handler is None:
+        return None
+
+    if Hub.current.get_integration(SanicIntegration) is None:
+        return old_error_handler
+
+    async def sentry_wrapped_error_handler(request, exception):
+        # type: (Request, Exception) -> Any
+        try:
+            response = old_error_handler(request, exception)
+            if isawaitable(response):
+                response = await response
+            return response
+        except Exception:
+            # Report errors that occur in Sanic error handler. These
+            # exceptions will not even show up in Sanic's
+            # `sanic.exceptions` logger.
+            exc_info = sys.exc_info()
+            _capture_exception(exc_info)
+            reraise(*exc_info)
+        finally:
+            # As mentioned in previous comment in _startup, this can be removed
+            # after https://github.com/sanic-org/sanic/issues/2297 is resolved
+            if SanicIntegration.version >= (21, 9):
+                await _hub_exit(request)
+
+    return sentry_wrapped_error_handler
+
+
+async def _legacy_handle_request(self, request, *args, **kwargs):
+    # type: (Any, Request, *Any, **Any) -> Any
+    hub = Hub.current
+    if hub.get_integration(SanicIntegration) is None:
+        return old_handle_request(self, request, *args, **kwargs)
+
+    weak_request = weakref.ref(request)
+
+    with Hub(hub) as hub:
+        with hub.configure_scope() as scope:
+            scope.clear_breadcrumbs()
+            scope.add_event_processor(_make_request_processor(weak_request))
+
+        response = old_handle_request(self, request, *args, **kwargs)
+        if isawaitable(response):
+            response = await response
+
+        return response
+
+
+def _legacy_router_get(self, *args):
+    # type: (Any, Union[Any, Request]) -> Any
+    rv = old_router_get(self, *args)
+    hub = Hub.current
+    if hub.get_integration(SanicIntegration) is not None:
+        with capture_internal_exceptions():
+            with hub.configure_scope() as scope:
+                if SanicIntegration.version and SanicIntegration.version >= 
(21, 3):
+                    # Sanic versions above and including 21.3 append the app 
name to the
+                    # route name, and so we need to remove it from Route name 
so the
+                    # transaction name is consistent across all versions
+                    sanic_app_name = self.ctx.app.name
+                    sanic_route = rv[0].name
+
+                    if sanic_route.startswith("%s." % sanic_app_name):
+                        # We add a 1 to the len of the sanic_app_name because 
there is a dot
+                        # that joins app name and the route name
+                        # Format: app_name.route_name
+                        sanic_route = sanic_route[len(sanic_app_name) + 1 :]
+
+                    scope.transaction = sanic_route
+                else:
+                    scope.transaction = rv[0].__name__
+    return rv
 
 
 def _capture_exception(exception):
@@ -211,39 +329,3 @@
         return event
 
     return sanic_processor
-
-
-class SanicRequestExtractor(RequestExtractor):
-    def content_length(self):
-        # type: () -> int
-        if self.request.body is None:
-            return 0
-        return len(self.request.body)
-
-    def cookies(self):
-        # type: () -> Dict[str, str]
-        return dict(self.request.cookies)
-
-    def raw_data(self):
-        # type: () -> bytes
-        return self.request.body
-
-    def form(self):
-        # type: () -> RequestParameters
-        return self.request.form
-
-    def is_json(self):
-        # type: () -> bool
-        raise NotImplementedError()
-
-    def json(self):
-        # type: () -> Optional[Any]
-        return self.request.json
-
-    def files(self):
-        # type: () -> RequestParameters
-        return self.request.files
-
-    def size_of_file(self, file):
-        # type: (Any) -> int
-        return len(file.body or ())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sentry-python-1.4.1/sentry_sdk/tracing.py 
new/sentry-python-1.5.0/sentry_sdk/tracing.py
--- old/sentry-python-1.4.1/sentry_sdk/tracing.py       2021-09-22 
14:34:25.000000000 +0200
+++ new/sentry-python-1.5.0/sentry_sdk/tracing.py       2021-11-16 
19:57:37.000000000 +0100
@@ -617,7 +617,7 @@
 
         1. If a sampling decision is passed to `start_transaction`
         (`start_transaction(name: "my transaction", sampled: True)`), that
-        decision will be used, regardlesss of anything else
+        decision will be used, regardless of anything else
 
         2. If `traces_sampler` is defined, its decision will be used. It can
         choose to keep or ignore any parent sampling decision, or use the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sentry-python-1.4.1/sentry_sdk/tracing_utils.py 
new/sentry-python-1.5.0/sentry_sdk/tracing_utils.py
--- old/sentry-python-1.4.1/sentry_sdk/tracing_utils.py 2021-09-22 
14:34:25.000000000 +0200
+++ new/sentry-python-1.5.0/sentry_sdk/tracing_utils.py 2021-11-16 
19:57:37.000000000 +0100
@@ -65,7 +65,7 @@
 # of the form `sentry=xxxx`
 SENTRY_TRACESTATE_ENTRY_REGEX = re.compile(
     # either sentry is the first entry or there's stuff immediately before it,
-    # ending in a commma (this prevents matching something like 
`coolsentry=xxx`)
+    # ending in a comma (this prevents matching something like 
`coolsentry=xxx`)
     "(?:^|.+,)"
     # sentry's part, not including the potential comma
     "(sentry=[^,]*)"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sentry-python-1.4.1/sentry_sdk/transport.py 
new/sentry-python-1.5.0/sentry_sdk/transport.py
--- old/sentry-python-1.4.1/sentry_sdk/transport.py     2021-09-22 
14:34:25.000000000 +0200
+++ new/sentry-python-1.5.0/sentry_sdk/transport.py     2021-11-16 
19:57:37.000000000 +0100
@@ -356,7 +356,10 @@
             else:
                 new_items.append(item)
 
-        envelope.items[:] = new_items
+        # Since we're modifying the envelope here make a copy so that others
+        # that hold references do not see their envelope modified.
+        envelope = Envelope(headers=envelope.headers, items=new_items)
+
         if not envelope.items:
             return None
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sentry-python-1.4.1/setup.py 
new/sentry-python-1.5.0/setup.py
--- old/sentry-python-1.4.1/setup.py    2021-09-22 14:34:25.000000000 +0200
+++ new/sentry-python-1.5.0/setup.py    2021-11-16 19:57:37.000000000 +0100
@@ -21,7 +21,7 @@
 
 setup(
     name="sentry-sdk",
-    version="1.4.1",
+    version="1.5.0",
     author="Sentry Team and Contributors",
     author_email="he...@sentry.io",
     url="https://github.com/getsentry/sentry-python";,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/sentry-python-1.4.1/tests/integrations/aws_lambda/test_aws.py 
new/sentry-python-1.5.0/tests/integrations/aws_lambda/test_aws.py
--- old/sentry-python-1.4.1/tests/integrations/aws_lambda/test_aws.py   
2021-09-22 14:34:25.000000000 +0200
+++ new/sentry-python-1.5.0/tests/integrations/aws_lambda/test_aws.py   
2021-11-16 19:57:37.000000000 +0100
@@ -105,7 +105,9 @@
     return get_boto_client()
 
 
-@pytest.fixture(params=["python3.6", "python3.7", "python3.8", "python2.7"])
+@pytest.fixture(
+    params=["python3.6", "python3.7", "python3.8", "python3.9", "python2.7"]
+)
 def lambda_runtime(request):
     return request.param
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/sentry-python-1.4.1/tests/integrations/beam/test_beam.py 
new/sentry-python-1.5.0/tests/integrations/beam/test_beam.py
--- old/sentry-python-1.4.1/tests/integrations/beam/test_beam.py        
2021-09-22 14:34:25.000000000 +0200
+++ new/sentry-python-1.5.0/tests/integrations/beam/test_beam.py        
2021-11-16 19:57:37.000000000 +0100
@@ -152,7 +152,9 @@
 
 
 class _OutputProcessor(OutputProcessor):
-    def process_outputs(self, windowed_input_element, results):
+    def process_outputs(
+        self, windowed_input_element, results, watermark_estimator=None
+    ):
         print(windowed_input_element)
         try:
             for result in results:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/sentry-python-1.4.1/tests/integrations/sanic/test_sanic.py 
new/sentry-python-1.5.0/tests/integrations/sanic/test_sanic.py
--- old/sentry-python-1.4.1/tests/integrations/sanic/test_sanic.py      
2021-09-22 14:34:25.000000000 +0200
+++ new/sentry-python-1.5.0/tests/integrations/sanic/test_sanic.py      
2021-11-16 19:57:37.000000000 +0100
@@ -173,11 +173,6 @@
             kwargs["app"] = app
 
         if SANIC_VERSION >= (21, 3):
-            try:
-                app.router.reset()
-                app.router.finalize()
-            except AttributeError:
-                ...
 
             class MockAsyncStreamer:
                 def __init__(self, request_body):
@@ -203,6 +198,13 @@
             patched_request = request.Request(**kwargs)
             patched_request.stream = MockAsyncStreamer([b"hello", b"foo"])
 
+            if SANIC_VERSION >= (21, 9):
+                await app.dispatch(
+                    "http.lifecycle.request",
+                    context={"request": patched_request},
+                    inline=True,
+                )
+
             await app.handle_request(
                 patched_request,
             )
@@ -217,6 +219,15 @@
         assert r.status == 200
 
     async def runner():
+        if SANIC_VERSION >= (21, 3):
+            if SANIC_VERSION >= (21, 9):
+                await app._startup()
+            else:
+                try:
+                    app.router.reset()
+                    app.router.finalize()
+                except AttributeError:
+                    ...
         await asyncio.gather(*(task(i) for i in range(1000)))
 
     if sys.version_info < (3, 7):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sentry-python-1.4.1/tests/test_basics.py 
new/sentry-python-1.5.0/tests/test_basics.py
--- old/sentry-python-1.4.1/tests/test_basics.py        2021-09-22 
14:34:25.000000000 +0200
+++ new/sentry-python-1.5.0/tests/test_basics.py        2021-11-16 
19:57:37.000000000 +0100
@@ -77,9 +77,13 @@
     assert Hub.current.last_event_id() == event_id
 
 
-def test_option_callback(sentry_init, capture_events):
+def test_option_callback(sentry_init, capture_events, monkeypatch):
     drop_events = False
     drop_breadcrumbs = False
+    reports = []
+
+    def record_lost_event(reason, data_category=None, item=None):
+        reports.append((reason, data_category))
 
     def before_send(event, hint):
         assert isinstance(hint["exc_info"][1], ValueError)
@@ -96,6 +100,10 @@
     sentry_init(before_send=before_send, before_breadcrumb=before_breadcrumb)
     events = capture_events()
 
+    monkeypatch.setattr(
+        Hub.current.client.transport, "record_lost_event", record_lost_event
+    )
+
     def do_this():
         add_breadcrumb(message="Hello", hint={"foo": 42})
         try:
@@ -106,8 +114,10 @@
     do_this()
     drop_breadcrumbs = True
     do_this()
+    assert not reports
     drop_events = True
     do_this()
+    assert reports == [("before_send", "error")]
 
     normal, no_crumbs = events
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sentry-python-1.4.1/tests/test_envelope.py 
new/sentry-python-1.5.0/tests/test_envelope.py
--- old/sentry-python-1.4.1/tests/test_envelope.py      2021-09-22 
14:34:25.000000000 +0200
+++ new/sentry-python-1.5.0/tests/test_envelope.py      2021-11-16 
19:57:37.000000000 +0100
@@ -132,3 +132,135 @@
             "event_id": "15210411201320122115110420122013",
             "sent_at": "2012-11-21T12:31:12.415908Z",
         }
+
+
+def test_envelope_with_sized_items():
+    """
+    Tests that it successfully parses envelopes with
+    the item size specified in the header
+    """
+    envelope_raw = (
+        b'{"event_id":"9ec79c33ec9942ab8353589fcb2e04dc"}\n'
+        + b'{"type":"type1","length":4 }\n1234\n'
+        + b'{"type":"type2","length":4 }\nabcd\n'
+        + b'{"type":"type3","length":0}\n\n'
+        + b'{"type":"type4","length":4 }\nab12\n'
+    )
+    envelope_raw_eof_terminated = envelope_raw[:-1]
+
+    for envelope_raw in (envelope_raw, envelope_raw_eof_terminated):
+        actual = Envelope.deserialize(envelope_raw)
+
+        items = [item for item in actual]
+
+        assert len(items) == 4
+
+        assert items[0].type == "type1"
+        assert items[0].get_bytes() == b"1234"
+
+        assert items[1].type == "type2"
+        assert items[1].get_bytes() == b"abcd"
+
+        assert items[2].type == "type3"
+        assert items[2].get_bytes() == b""
+
+        assert items[3].type == "type4"
+        assert items[3].get_bytes() == b"ab12"
+
+        assert actual.headers["event_id"] == "9ec79c33ec9942ab8353589fcb2e04dc"
+
+
+def test_envelope_with_implicitly_sized_items():
+    """
+    Tests that it successfully parses envelopes with
+    the item size not specified in the header
+    """
+    envelope_raw = (
+        b'{"event_id":"9ec79c33ec9942ab8353589fcb2e04dc"}\n'
+        + b'{"type":"type1"}\n1234\n'
+        + b'{"type":"type2"}\nabcd\n'
+        + b'{"type":"type3"}\n\n'
+        + b'{"type":"type4"}\nab12\n'
+    )
+    envelope_raw_eof_terminated = envelope_raw[:-1]
+
+    for envelope_raw in (envelope_raw, envelope_raw_eof_terminated):
+        actual = Envelope.deserialize(envelope_raw)
+        assert actual.headers["event_id"] == "9ec79c33ec9942ab8353589fcb2e04dc"
+
+        items = [item for item in actual]
+
+        assert len(items) == 4
+
+        assert items[0].type == "type1"
+        assert items[0].get_bytes() == b"1234"
+
+        assert items[1].type == "type2"
+        assert items[1].get_bytes() == b"abcd"
+
+        assert items[2].type == "type3"
+        assert items[2].get_bytes() == b""
+
+        assert items[3].type == "type4"
+        assert items[3].get_bytes() == b"ab12"
+
+
+def test_envelope_with_two_attachments():
+    """
+    Test that items are correctly parsed in an envelope with to size specified 
items
+    """
+    two_attachments = (
+        
b'{"event_id":"9ec79c33ec9942ab8353589fcb2e04dc","dsn":"https://e12d836b15bb49d7bbf99e64295d995b:@sentry.io/42"}\n'
+        + 
b'{"type":"attachment","length":10,"content_type":"text/plain","filename":"hello.txt"}\n'
+        + b"\xef\xbb\xbfHello\r\n\n"
+        + 
b'{"type":"event","length":41,"content_type":"application/json","filename":"application.log"}\n'
+        + b'{"message":"hello world","level":"error"}\n'
+    )
+    two_attachments_eof_terminated = two_attachments[
+        :-1
+    ]  # last \n is optional, without it should still be a valid envelope
+
+    for envelope_raw in (two_attachments, two_attachments_eof_terminated):
+        actual = Envelope.deserialize(envelope_raw)
+        items = [item for item in actual]
+
+        assert len(items) == 2
+        assert items[0].get_bytes() == b"\xef\xbb\xbfHello\r\n"
+        assert items[1].payload.json == {"message": "hello world", "level": 
"error"}
+
+
+def test_envelope_with_empty_attachments():
+    """
+    Test that items are correctly parsed in an envelope with two 0 length 
items (with size specified in the header
+    """
+    two_empty_attachments = (
+        b'{"event_id":"9ec79c33ec9942ab8353589fcb2e04dc"}\n'
+        + b'{"type":"attachment","length":0}\n\n'
+        + b'{"type":"attachment","length":0}\n\n'
+    )
+
+    two_empty_attachments_eof_terminated = two_empty_attachments[
+        :-1
+    ]  # last \n is optional, without it should still be a valid envelope
+
+    for envelope_raw in (two_empty_attachments, 
two_empty_attachments_eof_terminated):
+        actual = Envelope.deserialize(envelope_raw)
+        items = [item for item in actual]
+
+        assert len(items) == 2
+        assert items[0].get_bytes() == b""
+        assert items[1].get_bytes() == b""
+
+
+def test_envelope_without_headers():
+    """
+    Test that an envelope without headers is parsed successfully
+    """
+    envelope_without_headers = (
+        b"{}\n" + b'{"type":"session"}\n' + b'{"started": 
"2020-02-07T14:16:00Z"}'
+    )
+    actual = Envelope.deserialize(envelope_without_headers)
+    items = [item for item in actual]
+
+    assert len(items) == 1
+    assert items[0].payload.get_bytes() == b'{"started": 
"2020-02-07T14:16:00Z"}'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sentry-python-1.4.1/tests/test_transport.py 
new/sentry-python-1.5.0/tests/test_transport.py
--- old/sentry-python-1.4.1/tests/test_transport.py     2021-09-22 
14:34:25.000000000 +0200
+++ new/sentry-python-1.5.0/tests/test_transport.py     2021-11-16 
19:57:37.000000000 +0100
@@ -279,7 +279,7 @@
     client.flush()
 
     # this goes out with an extra envelope because it's flushed after the last 
item
-    # that is normally in the queue.  This is quite funny in a way beacuse it 
means
+    # that is normally in the queue.  This is quite funny in a way because it 
means
     # that the envelope that caused its own over quota report (an error with an
     # attachment) will include its outcome since it's pending.
     assert len(capturing_server.captured) == 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sentry-python-1.4.1/tox.ini 
new/sentry-python-1.5.0/tox.ini
--- old/sentry-python-1.4.1/tox.ini     2021-09-22 14:34:25.000000000 +0200
+++ new/sentry-python-1.5.0/tox.ini     2021-11-16 19:57:37.000000000 +0100
@@ -46,7 +46,7 @@
     {pypy,py2.7,py3.5,py3.6,py3.7,py3.8}-celery-{4.3,4.4}
     {py3.6,py3.7,py3.8}-celery-5.0
 
-    py3.7-beam-{2.12,2.13}
+    py3.7-beam-{2.12,2.13,2.32,2.33}
 
     # The aws_lambda tests deploy to the real AWS and have their own matrix of 
Python versions.
     py3.7-aws_lambda
@@ -140,6 +140,8 @@
 
     beam-2.12: apache-beam>=2.12.0, <2.13.0
     beam-2.13: apache-beam>=2.13.0, <2.14.0
+    beam-2.32: apache-beam>=2.32.0, <2.33.0
+    beam-2.33: apache-beam>=2.33.0, <2.34.0
     beam-master: 
git+https://github.com/apache/beam#egg=apache-beam&subdirectory=sdks/python
 
     celery: redis
@@ -300,6 +302,9 @@
     {py3.5,py3.6,py3.7,py3.8,py3.9}-flask-{0.10,0.11,0.12}: pip install 
pytest<5
     {py3.6,py3.7,py3.8,py3.9}-flask-{0.11}: pip install Werkzeug<2
 
+    ; https://github.com/more-itertools/more-itertools/issues/578
+    py3.5-flask-{0.10,0.11,0.12}: pip install more-itertools<8.11.0
+
     py.test {env:TESTPATH} {posargs}
 
 [testenv:linters]

Reply via email to