Skip to content

Commit cfecca1

Browse files
alrexc24t
alrex
authored andcommitted
Ensure the API returns right value types (open-telemetry#307)
Fixes open-telemetry#142 Enabling --strict mode for mypy. Added a test in the sdk and the same test in the api to test the different behaviours between the Tracer, Span and Metric classes.
1 parent 15991af commit cfecca1

File tree

8 files changed

+129
-13
lines changed

8 files changed

+129
-13
lines changed

mypy.ini

+5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@
1010
disallow_incomplete_defs = True
1111
check_untyped_defs = True
1212
disallow_untyped_decorators = True
13+
warn_unused_configs = True
1314
warn_unused_ignores = True
1415
warn_return_any = True
16+
warn_redundant_casts = True
1517
strict_equality = True
18+
strict_optional = True
19+
no_implicit_optional = True
20+
no_implicit_reexport = True

opentelemetry-api/src/opentelemetry/metrics/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ def create_metric(
218218
unit: str,
219219
value_type: Type[ValueT],
220220
metric_type: Type[MetricT],
221-
label_keys: Sequence[str] = None,
221+
label_keys: Sequence[str] = (),
222222
enabled: bool = True,
223223
monotonic: bool = False,
224224
) -> "Metric":

opentelemetry-api/src/opentelemetry/trace/__init__.py

+8-4
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ class SpanKind(enum.Enum):
145145
class Span:
146146
"""A span represents a single operation within a trace."""
147147

148-
def end(self, end_time: int = None) -> None:
148+
def end(self, end_time: typing.Optional[int] = None) -> None:
149149
"""Sets the current time as the span's end time.
150150
151151
The span's end time is the wall time at which the operation finished.
@@ -163,6 +163,8 @@ def get_context(self) -> "SpanContext":
163163
Returns:
164164
A :class:`.SpanContext` with a copy of this span's immutable state.
165165
"""
166+
# pylint: disable=no-self-use
167+
return INVALID_SPAN_CONTEXT
166168

167169
def set_attribute(self, key: str, value: types.AttributeValue) -> None:
168170
"""Sets an Attribute.
@@ -174,7 +176,7 @@ def add_event(
174176
self,
175177
name: str,
176178
attributes: types.Attributes = None,
177-
timestamp: int = None,
179+
timestamp: typing.Optional[int] = None,
178180
) -> None:
179181
"""Adds an `Event`.
180182
@@ -204,6 +206,8 @@ def is_recording_events(self) -> bool:
204206
Returns true if this Span is active and recording information like
205207
events with the add_event operation and attributes using set_attribute.
206208
"""
209+
# pylint: disable=no-self-use
210+
return False
207211

208212
def set_status(self, status: Status) -> None:
209213
"""Sets the Status of the Span. If used, this will override the default
@@ -298,8 +302,8 @@ def __init__(
298302
self,
299303
trace_id: int,
300304
span_id: int,
301-
trace_options: "TraceOptions" = None,
302-
trace_state: "TraceState" = None,
305+
trace_options: "TraceOptions" = DEFAULT_TRACE_OPTIONS,
306+
trace_state: "TraceState" = DEFAULT_TRACE_STATE,
303307
) -> None:
304308
if trace_options is None:
305309
trace_options = DEFAULT_TRACE_OPTIONS

opentelemetry-api/src/opentelemetry/trace/sampling.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def __repr__(self) -> str:
3636
def __init__(
3737
self,
3838
sampled: bool = False,
39-
attributes: Mapping[str, "AttributeValue"] = None,
39+
attributes: Optional[Mapping[str, "AttributeValue"]] = None,
4040
) -> None:
4141
self.sampled = sampled # type: bool
4242
if attributes is None:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Copyright 2019, OpenTelemetry Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import unittest
16+
17+
from opentelemetry import metrics, trace
18+
19+
20+
class TestAPIOnlyImplementation(unittest.TestCase):
21+
"""
22+
This test is in place to ensure the API is returning values that
23+
are valid. The same tests have been added to the SDK with
24+
different expected results. See issue for more details:
25+
https://github.com/open-telemetry/opentelemetry-python/issues/142
26+
"""
27+
28+
def test_tracer(self):
29+
tracer = trace.Tracer()
30+
with tracer.start_span("test") as span:
31+
self.assertEqual(span.get_context(), trace.INVALID_SPAN_CONTEXT)
32+
self.assertEqual(span, trace.INVALID_SPAN)
33+
self.assertIs(span.is_recording_events(), False)
34+
with tracer.start_span("test2") as span2:
35+
self.assertEqual(
36+
span2.get_context(), trace.INVALID_SPAN_CONTEXT
37+
)
38+
self.assertEqual(span2, trace.INVALID_SPAN)
39+
self.assertIs(span2.is_recording_events(), False)
40+
41+
def test_span(self):
42+
span = trace.Span()
43+
self.assertEqual(span.get_context(), trace.INVALID_SPAN_CONTEXT)
44+
self.assertIs(span.is_recording_events(), False)
45+
46+
def test_default_span(self):
47+
span = trace.DefaultSpan(trace.INVALID_SPAN_CONTEXT)
48+
self.assertEqual(span.get_context(), trace.INVALID_SPAN_CONTEXT)
49+
self.assertIs(span.is_recording_events(), False)
50+
51+
def test_meter(self):
52+
meter = metrics.Meter()
53+
metric = meter.create_metric("", "", "", float, metrics.Counter)
54+
self.assertIsInstance(metric, metrics.DefaultMetric)

opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def __init__(
103103
description: str,
104104
unit: str,
105105
value_type: Type[metrics_api.ValueT],
106-
label_keys: Sequence[str] = None,
106+
label_keys: Sequence[str] = (),
107107
enabled: bool = True,
108108
monotonic: bool = False,
109109
):
@@ -150,7 +150,7 @@ def __init__(
150150
description: str,
151151
unit: str,
152152
value_type: Type[metrics_api.ValueT],
153-
label_keys: Sequence[str] = None,
153+
label_keys: Sequence[str] = (),
154154
enabled: bool = True,
155155
monotonic: bool = True,
156156
):
@@ -186,7 +186,7 @@ def __init__(
186186
description: str,
187187
unit: str,
188188
value_type: Type[metrics_api.ValueT],
189-
label_keys: Sequence[str] = None,
189+
label_keys: Sequence[str] = (),
190190
enabled: bool = True,
191191
monotonic: bool = False,
192192
):
@@ -222,7 +222,7 @@ def __init__(
222222
description: str,
223223
unit: str,
224224
value_type: Type[metrics_api.ValueT],
225-
label_keys: Sequence[str] = None,
225+
label_keys: Sequence[str] = (),
226226
enabled: bool = False,
227227
monotonic: bool = False,
228228
):
@@ -269,7 +269,7 @@ def create_metric(
269269
unit: str,
270270
value_type: Type[metrics_api.ValueT],
271271
metric_type: Type[metrics_api.MetricT],
272-
label_keys: Sequence[str] = None,
272+
label_keys: Sequence[str] = (),
273273
enabled: bool = True,
274274
monotonic: bool = False,
275275
) -> metrics_api.MetricT:

opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ def add_event(
204204
self,
205205
name: str,
206206
attributes: types.Attributes = None,
207-
timestamp: int = None,
207+
timestamp: Optional[int] = None,
208208
) -> None:
209209
self.add_lazy_event(
210210
trace_api.Event(
@@ -241,7 +241,7 @@ def start(self, start_time: Optional[int] = None) -> None:
241241
return
242242
self.span_processor.on_start(self)
243243

244-
def end(self, end_time: int = None) -> None:
244+
def end(self, end_time: Optional[int] = None) -> None:
245245
with self._lock:
246246
if not self.is_recording_events():
247247
return
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Copyright 2019, OpenTelemetry Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import unittest
16+
17+
from opentelemetry.metrics import DefaultMetric
18+
from opentelemetry.sdk import metrics, trace
19+
from opentelemetry.trace import INVALID_SPAN, INVALID_SPAN_CONTEXT
20+
21+
22+
class TestSDKImplementation(unittest.TestCase):
23+
"""
24+
This test is in place to ensure the SDK implementation of the API
25+
is returning values that are valid. The same tests have been added
26+
to the API with different expected results. See issue for more details:
27+
https://github.com/open-telemetry/opentelemetry-python/issues/142
28+
"""
29+
30+
def test_tracer(self):
31+
tracer = trace.Tracer()
32+
with tracer.start_span("test") as span:
33+
self.assertNotEqual(span.get_context(), INVALID_SPAN_CONTEXT)
34+
self.assertNotEqual(span, INVALID_SPAN)
35+
self.assertIs(span.is_recording_events(), True)
36+
with tracer.start_span("test2") as span2:
37+
self.assertNotEqual(span2.get_context(), INVALID_SPAN_CONTEXT)
38+
self.assertNotEqual(span2, INVALID_SPAN)
39+
self.assertIs(span2.is_recording_events(), True)
40+
41+
def test_span(self):
42+
with self.assertRaises(Exception):
43+
# pylint: disable=no-value-for-parameter
44+
span = trace.Span()
45+
46+
span = trace.Span("name", INVALID_SPAN_CONTEXT)
47+
self.assertEqual(span.get_context(), INVALID_SPAN_CONTEXT)
48+
self.assertIs(span.is_recording_events(), True)
49+
50+
def test_meter(self):
51+
meter = metrics.Meter()
52+
metric = meter.create_metric("", "", "", float, metrics.Counter)
53+
self.assertNotIsInstance(metric, DefaultMetric)

0 commit comments

Comments
 (0)