Skip to content

Commit 702d7f7

Browse files
author
Attila Sasvari
committed
This PR is based on open-telemetry#3995.
Part of open-telemetry#1608 Addressing running mypy on opentelemetry-sdk iteratively so we don't have to make one big change addressing all mypy issues at once.
1 parent a67f5f8 commit 702d7f7

File tree

2 files changed

+34
-20
lines changed

2 files changed

+34
-20
lines changed

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

+33-20
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@
6363
import typing
6464
from json import dumps
6565
from os import environ
66+
from types import ModuleType
67+
from typing import Dict, List, Optional, Union, cast
6668
from urllib import parse
6769

6870
from opentelemetry.attributes import BoundedAttributes
@@ -75,10 +77,14 @@
7577
from opentelemetry.util._importlib_metadata import entry_points, version
7678
from opentelemetry.util.types import AttributeValue
7779

80+
psutil: Optional[ModuleType] = None
81+
7882
try:
79-
import psutil
83+
import psutil as pustil_module
84+
85+
pustil = pustil_module
8086
except ImportError:
81-
psutil = None
87+
pass
8288

8389
LabelValue = AttributeValue
8490
Attributes = typing.Mapping[str, LabelValue]
@@ -147,6 +153,11 @@
147153
class Resource:
148154
"""A Resource is an immutable representation of the entity producing telemetry as Attributes."""
149155

156+
_attributes: Dict[
157+
str, Union[str, int, float, bool]
158+
] # Example: Adjust according to actual expected types
159+
_schema_url: str
160+
150161
def __init__(
151162
self, attributes: Attributes, schema_url: typing.Optional[str] = None
152163
):
@@ -173,7 +184,7 @@ def create(
173184
if not attributes:
174185
attributes = {}
175186

176-
resource_detectors = []
187+
resource_detectors: List[ResourceDetector] = []
177188

178189
resource = _DEFAULT_RESOURCE
179190

@@ -182,6 +193,7 @@ def create(
182193
).split(",")
183194

184195
if "otel" not in otel_experimental_resource_detectors:
196+
185197
otel_experimental_resource_detectors.append("otel")
186198

187199
for resource_detector in otel_experimental_resource_detectors:
@@ -193,9 +205,8 @@ def create(
193205
name=resource_detector.strip(),
194206
)
195207
)
196-
).load()()
208+
)
197209
)
198-
199210
resource = get_aggregated_resources(
200211
resource_detectors, _DEFAULT_RESOURCE
201212
).merge(Resource(attributes, schema_url))
@@ -206,7 +217,7 @@ def create(
206217
PROCESS_EXECUTABLE_NAME, None
207218
)
208219
if process_executable_name:
209-
default_service_name += ":" + process_executable_name
220+
default_service_name += ":" + str(process_executable_name)
210221
resource = resource.merge(
211222
Resource({SERVICE_NAME: default_service_name}, schema_url)
212223
)
@@ -218,6 +229,8 @@ def get_empty() -> "Resource":
218229

219230
@property
220231
def attributes(self) -> Attributes:
232+
if self._attributes is None:
233+
raise ValueError("Attributes are not set.")
221234
return self._attributes
222235

223236
@property
@@ -241,7 +254,7 @@ def merge(self, other: "Resource") -> "Resource":
241254
Returns:
242255
The newly-created Resource.
243256
"""
244-
merged_attributes = self.attributes.copy()
257+
merged_attributes = dict(self.attributes)
245258
merged_attributes.update(other.attributes)
246259

247260
if self.schema_url == "":
@@ -257,7 +270,6 @@ def merge(self, other: "Resource") -> "Resource":
257270
other.schema_url,
258271
)
259272
return self
260-
261273
return Resource(merged_attributes, schema_url)
262274

263275
def __eq__(self, other: object) -> bool:
@@ -268,15 +280,15 @@ def __eq__(self, other: object) -> bool:
268280
and self._schema_url == other._schema_url
269281
)
270282

271-
def __hash__(self):
272-
return hash(
273-
f"{dumps(self._attributes.copy(), sort_keys=True)}|{self._schema_url}"
274-
)
283+
def __hash__(self) -> int:
284+
attributes_json = dumps(self._attributes.copy(), sort_keys=True)
285+
return hash(f"{attributes_json}|{self._schema_url}")
275286

276-
def to_json(self, indent=4) -> str:
287+
def to_json(self, indent: int = 4) -> str:
288+
attributes = dict(self._attributes)
277289
return dumps(
278290
{
279-
"attributes": dict(self._attributes),
291+
"attributes": attributes,
280292
"schema_url": self._schema_url,
281293
},
282294
indent=indent,
@@ -294,7 +306,7 @@ def to_json(self, indent=4) -> str:
294306

295307

296308
class ResourceDetector(abc.ABC):
297-
def __init__(self, raise_on_error=False):
309+
def __init__(self, raise_on_error: bool = False) -> None:
298310
self.raise_on_error = raise_on_error
299311

300312
@abc.abstractmethod
@@ -343,7 +355,7 @@ def detect(self) -> "Resource":
343355
),
344356
)
345357
)
346-
_process_pid = os.getpid()
358+
_process_pid = str(os.getpid())
347359
_process_executable_name = sys.executable
348360
_process_executable_path = os.path.dirname(_process_executable_name)
349361
_process_command = sys.argv[0]
@@ -358,23 +370,24 @@ def detect(self) -> "Resource":
358370
PROCESS_EXECUTABLE_PATH: _process_executable_path,
359371
PROCESS_COMMAND: _process_command,
360372
PROCESS_COMMAND_LINE: _process_command_line,
361-
PROCESS_COMMAND_ARGS: _process_command_args,
373+
PROCESS_COMMAND_ARGS: "".join(_process_command_args),
362374
}
363375
if hasattr(os, "getppid"):
364376
# pypy3 does not have getppid()
365-
resource_info[PROCESS_PARENT_PID] = os.getppid()
377+
resource_info[PROCESS_PARENT_PID] = str(os.getppid())
366378

367379
if psutil is not None:
368380
process = psutil.Process()
369-
resource_info[PROCESS_OWNER] = process.username()
381+
username = cast(str, process.username())
382+
resource_info[PROCESS_OWNER] = username
370383

371384
return Resource(resource_info)
372385

373386

374387
def get_aggregated_resources(
375388
detectors: typing.List["ResourceDetector"],
376389
initial_resource: typing.Optional[Resource] = None,
377-
timeout=5,
390+
timeout: int = 5,
378391
) -> "Resource":
379392
"""Retrieves resources from detectors in the order that they were passed
380393

tox.ini

+1
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ commands =
332332
coverage: {toxinidir}/scripts/coverage.sh
333333

334334
mypy: mypy --install-types --non-interactive --namespace-packages --explicit-package-bases opentelemetry-api/src/opentelemetry/
335+
mypy: mypy --install-types --non-interactive --namespace-packages --explicit-package-bases opentelemetry-sdk/src/opentelemetry/sdk/resources
335336
mypy: mypy --install-types --non-interactive --namespace-packages --explicit-package-bases opentelemetry-semantic-conventions/src/opentelemetry/semconv/
336337

337338
; For test code, we don't want to enforce the full mypy strictness

0 commit comments

Comments
 (0)