8000 ref: Add typehints (#270) · etherscan-io/sentry-python@7413329 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7413329

Browse files
authored
ref: Add typehints (getsentry#270)
* ref: Add mypy * fix: Nicer api for push-scope * fix: Review comments * fix: Dont import from typing * fix: Ultimate signature for push_scope and configure_scope * fix: Restore submodule link in apidocs * fix: Remove unused type * fix: ImportError
1 parent 1d380f7 commit 7413329

35 files changed

+837
-158
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ venv
2121
.hypothesis
2222
semaphore
2323
pip-wheel-metadata
24+
.mypy_cache

mypy.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[mypy]
2+
allow_redefinition = True

sentry_sdk/__init__.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,25 @@
2222
except Exception as e:
2323
sentry_sdk.capture_exception(e)
2424
"""
25+
from sentry_sdk.hub import Hub, init
26+
from sentry_sdk.scope import Scope
27+
from sentry_sdk.transport import Transport, HttpTransport
28+
from sentry_sdk.client import Client
29+
2530
from sentry_sdk.api import * # noqa
26-
from sentry_sdk.api import __all__ # noqa
31+
from sentry_sdk.api import __all__ as api_all
32+
2733
from sentry_sdk.consts import VERSION # noqa
2834

29-
# modules we consider public
30-
__all__.append("integrations")
35+
__all__ = api_all + [ # noqa
36+
"Hub",
37+
"Scope",
38+
"Client",
39+
"Transport",
40+
"HttpTransport",
41+
"init",
42+
"integrations",
43+
]
3144

3245
# Initialize the debug support after everything is loaded
3346
from sentry_sdk.debug import init_debug_support

sentry_sdk/_compat.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import sys
22

3+
if False:
4+
from typing import Optional
5+
from typing import Tuple
6+
from typing import Any
7+
from typing import Type
8+
39

410
PY2 = sys.version_info[0] == 2
511

@@ -27,8 +33,8 @@ def implements_str(cls):
2733
import queue # noqa
2834

2935
text_type = str
30-
string_types = (text_type,)
31-
number_types = (int, float)
36+
string_types = (text_type,) # type: Tuple[type]
37+
number_types = (int, float) # type: Tuple[type, type]
3238
int_types = (int,) # noqa
3339
iteritems = lambda x: x.items()
3440

@@ -39,6 +45,8 @@ def implements_str(x):
3945
return x
4046

4147
def reraise(tp, value, tb=None):
48+
# type: (Optional[Type[BaseException]], Optional[BaseException], Optional[Any]) -> None
49+
assert value is not None
4250
if value.__traceback__ is not tb:
4351
raise value.with_traceback(tb)
4452
raise value
@@ -53,8 +61,9 @@ def __new__(cls, name, this_bases, d):
5361

5462

5563
def check_thread_support():
64+
# type: () -> None
5665
try:
57-
from uwsgi import opt
66+
from uwsgi import opt # type: ignore
5867
except ImportError:
5968
return
6069

sentry_sdk/api.py

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
import inspect
22
from contextlib import contextmanager
33

4-
from sentry_sdk.hub import Hub, init
4+
from sentry_sdk.hub import Hub
55
from sentry_sdk.scope import Scope
6-
from sentry_sdk.transport import Transport, HttpTransport
7-
from sentry_sdk.client import Client
86

97

10-
__all__ = ["Hub", "Scope", "Client", "Transport", "HttpTransport", "init"]
8+
if False:
9+
from typing import Any
10+
from typing import Optional
11+
from typing import overload
12+
from typing import Callable
13+
from contextlib import AbstractContextManager
14+
else:
1115

16+
def overload(x):
17+
return x
1218

13-
_initial_client = None
19+
20+
__all__ = []
1421

1522

1623
def public(f):
@@ -35,16 +42,20 @@ def capture_event(event, hint=None):
3542

3643
@hubmethod
3744
def capture_message(message, level=None):
45+
# type: (str, Optional[Any]) -> Optional[str]
3846
hub = Hub.current
3947
if hub is not None:
4048
return hub.capture_message(message, level)
49+
return None
4150

4251

4352
@hubmethod
4453
def capture_exception(error=None):
54+
# type: (ValueError) -> Optional[str]
4555
hub = Hub.current
4656
if hub is not None:
4757
return hub.capture_exception(error)
58+
return None
4859

4960

5061
@hubmethod
@@ -54,7 +65,19 @@ def add_breadcrumb(*args, **kwargs):
5465
return hub.add_breadcrumb(*args, **kwargs)
5566

5667

57-
@hubmethod
68+
@overload # noqa
69+
def configure_scope():
70+
# type: () -> AbstractContextManager
71+
pass
72+
73+
74+
@overload # noqa
75+
def configure_scope(callback):
76+
# type: (Callable) -> None
77+
pass
78+
79+
80+
@hubmethod # noqa
5881
def configure_scope(callback=None):
5982
hub = Hub.current
6083
if hub is not None:
@@ -66,9 +89,24 @@ def inner():
6689
yield Scope()
6790

6891
return inner()
92+
else:
93+
# returned if user provided callback
94+
return None
6995

7096

71-
@hubmethod
97+
@overload # noqa
98+
def push_scope():
99+
# type: () -> AbstractContextManager
100+
pass
101+
102+
103+
@overload # noqa
104+
def push_scope(callback):
105+
# type: (Callable) -> None
106+
pass
107+
108+
109+
@hubmethod # noqa
72110
def push_scope(callback=None):
73111
hub = Hub.current
74112
if hub is not None:
@@ -80,6 +118,9 @@ def inner():
80118
yield Scope()
81119

82120
return inner()
121+
else:
122+
# returned if user provided callback
123+
return None
83124

84125

85126
@hubmethod
@@ -91,6 +132,8 @@ def flush(timeout=None, callback=None):
91132

92133
@hubmethod
93134
def last_event_id():
135+
# type: () -> Optional[str]
94136
hub = Hub.current
95137
if hub is not None:
96138
return hub.last_event_id()
139+
return None

sentry_sdk/client.py

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,31 +19,39 @@
1919
from sentry_sdk.integrations import setup_integrations
2020
from sentry_sdk.utils import ContextVar
2121

22+
if False:
23+
from sentry_sdk.consts import ClientOptions
24+
from sentry_sdk.scope import Scope
25+
from typing import Any
26+
from typing import Dict
27+
from typing import Optional
28+
2229

2330
_client_init_debug = ContextVar("client_init_debug")
2431

2532

2633
def get_options(*args, **kwargs):
34+
# type: (*str, **ClientOptions) -> ClientOptions
2735
if args and (isinstance(args[0], string_types) or args[0] is None):
28-
dsn = args[0]
36+
dsn = args[0] # type: Optional[str]
2937
args = args[1:]
3038
else:
3139
dsn = None
3240

3341
rv = dict(DEFAULT_OPTIONS)
34-
options = dict(*args, **kwargs)
42+
options = dict(*args, **kwargs) # type: ignore
3543
if dsn is not None and options.get("dsn") is None:
36-
options["dsn"] = dsn
44+
options["dsn"] = dsn # type: ignore
3745

3846
for key, value in options.items():
3947
if key not in rv:
4048
raise TypeError("Unknown option %r" % (key,))
41-
rv[key] = value
49+
rv[key] = value # type: ignore
4250

4351
if rv["dsn"] is None:
4452
rv["dsn"] = os.environ.get("SENTRY_DSN")
4553

46-
return rv
54+
return rv # type: ignore
4755

4856

4957
class Client(object):
@@ -54,6 +62,7 @@ class Client(object):
5462
"""
5563

5664
def __init__(self, *args, **kwargs):
65+
# type: (*str, **ClientOptions) -> None
5766
old_debug = _client_init_debug.get(False)
5867
try:
5968
self.options = options = get_options(*args, **kwargs)
@@ -79,7 +88,13 @@ def dsn(self):
7988
"""Returns the configured DSN as string."""
8089
return self.options["dsn"]
8190

82-
def _prepare_event(self, event, hint, scope):
91+
def _prepare_event(
92+
self,
93+
event, # type: Dict[str, Any]
94+
hint, # type: Optional[Dict[str, Any]]
95+
scope, # type: Optional[Scope]
96+
):
97+
# type: (...) -> Optional[Dict[str, Any]]
8398
if event.get("timestamp") is None:
8499
event["timestamp"] = datetime.utcnow()
85100

@@ -104,8 +119,8 @@ def _prepare_event(self, event, hint, scope):
104119
]
105120

106121
for key in "release", "environment", "server_name", "dist":
107-
if event.get(key) is None and self.options[key] is not None:
108-
event[key] = text_type(self.options[key]).strip()
122+
if event.get(key) is None and self.options[key] is not None: # type: ignore
123+
event[key] = text_type(self.options[key]).strip() # type: ignore
109124
if event.get("sdk") is None:
110125
sdk_info = dict(SDK_INFO)
111126
sdk_info["integrations"] = sorted(self.integrations.keys())
@@ -132,11 +147,12 @@ def _prepare_event(self, event, hint, scope):
132147
new_event = before_send(event, hint)
133148
if new_event is None:
134149
logger.info("before send dropped event (%s)", event)
135-
event = new_event
150+
event = new_event # type: ignore
136151

137152
return event
138153

139-
def _is_ignored_error(self, event, hint=None):
154+
def _is_ignored_error(self, event, hint):
155+
# type: (Dict[str, Any], Dict[str, Any]) -> bool
140156
exc_info = hint.get("exc_info")
141157
if exc_info is None:
142158
return False
@@ -156,7 +172,13 @@ def _is_ignored_error(self, event, hint=None):
156172

157173
return False
158174

159-
def _should_capture(self, event, hint, scope=None):
175+
def _should_capture(
176+
self,
177+
event, # type: Dict[str, Any]
178+
hint, # type: Dict[str, Any]
179+
scope=None, # type: Scope
180+
):
181+
# type: (...) -> bool
160182
if scope is not None and not scope._should_capture:
161183
return False
162184

@@ -172,6 +194,7 @@ def _should_capture(self, event, hint, scope=None):
172194
return True
173195

174196
def capture_event(self, event, hint=None, scope=None):
197+
# type: (Dict[str, Any], Any, Scope) -> Optional[str]
175198
"""Captures an event.
176199
177200
This takes the ready made event and an optoinal hint and scope. The
@@ -183,17 +206,17 @@ def capture_event(self, event, hint=None, scope=None):
183206
value of this function will be the ID of the captured event.
184207
"""
185208
if self.transport is None:
186-
return
209+
return None
187210
if hint is None:
188211
hint = {}
189212
rv = event.get("event_id")
190213
if rv is None:
191214
event["event_id"] = rv = uuid.uuid4().hex
192215
if not self._should_capture(event, hint, scope):
193-
return
194-
event = self._prepare_event(event, hint, scope)
216+
return None
217+
event = self._prepare_event(event, hint, scope) # type: ignore
195218
if event is None:
196-
return
219+
return None
197220
self.transport.capture_event(event)
198221
return rv
199222

sentry_sdk/consts.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,45 @@
11
import socket
22

3+
if False:
4+
from mypy_extensions import TypedDict
5+
from typing import Optional
6+
from typing import Callable
7+
from typing import Union
8+
from typing import List
9+
10+
from sentry_sdk.transport import Transport
11+
from sentry_sdk.integrations import Integration
12+
13+
ClientOptions = TypedDict(
14+
"ClientOptions",
15+
{
16+
"dsn": Optional[str],
17+
"with_locals": bool,
18+
"max_breadcrumbs": int,
19+
"release": Optional[str],
20+
"environment": Optional[str],
21+
"server_name": Optional[str],
22+
"shutdown_timeout": int,
23+
"integrations": List[Integration],
24+
"in_app_include": List[str],
25+
"in_app_exclude": List[str],
26+
"default_integrations": bool,
27+
"dist": Optional[str],
28+
"transport": Optional[Union[Transport, type, Callable]],
29+
"sample_rate": int,
30+
"send_default_pii": bool,
31+
"http_proxy": Optional[str],
32+
"https_proxy": Optional[str],
33+
"ignore_errors": List[type],
34+
"request_bodies": str,
35+
"before_send": Optional[Callable],
36+
"before_breadcrumb": Optional[Callable],
37+
"debug": bool,
38+
"attach_stacktrace": bool,
39+
"ca_certs": Optional[str],
40+
},
41+
)
42+
343

444
VERSION = "0.7.3"
545
DEFAULT_SERVER_NAME = socket.gethostname() if hasattr(socket, "gethostname") else None

sentry_sdk/debug.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
from sentry_sdk.hub import Hub
66
from sentry_sdk.utils import logger
77
from sentry_sdk.client import _client_init_debug
8+
from logging import LogRecord
89

910

1011
class _HubBasedClientFilter(logging.Filter):
1112
def filter(self, record):
13+
# type: (LogRecord) -> bool
1214
if _client_init_debug.get(False):
1315
return True
1416
hub = Hub.current

0 commit comments

Comments
 (0)
0