Skip to content

Commit 3f9a6cd

Browse files
committed
Fix factory return type (Optional) & improve docs.
1 parent e4a1dd3 commit 3f9a6cd

File tree

2 files changed

+45
-24
lines changed

2 files changed

+45
-24
lines changed

opentelemetry-api/src/opentelemetry/loader.py

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,35 @@
1717
The OpenTelemetry loader module is mainly used internally to load the
1818
implementation for global objects like :func:`opentelemetry.trace.tracer`.
1919
20-
When loading an implementation, the following algorithm is used:
20+
.. _loader-factory:
21+
22+
An instance of a global object of type ``T`` is always created with a factory
23+
function with the following signature::
24+
25+
def my_factory_for_t(api_type: typing.Type[T]) -> typing.Optional[T]:
26+
# ...
27+
28+
That function is called with e.g., the type of the global object it should
29+
create as an argument (e.g. the type object
30+
:class:`opentelemetry.trace.Tracer`) and should return an instance of that type
31+
(such that ``instanceof(my_factory_for_t(T), T)`` is true). Alternatively, it
32+
may return ``None`` to indicate that the no-op default should be used.
33+
34+
When loading an implementation, the following algorithm is used to find a
35+
factory function or other means to create the global object:
2136
2237
1. If the environment variable
2338
:samp:`OPENTELEMETRY_PYTHON_IMPLEMENTATION_{getter-name}` (e.g.,
2439
``OPENTELEMETRY_PYTHON_IMPLEMENTATION_TRACER``) is set to an nonempty
25-
value, an attempt is made to import a module with that name and call a
26-
function ``get_opentelemetry_implementation`` in it. The function
27-
receives the API type that is expected as an argument and should return
28-
an instance of it or ``None`` (e.g., the argument is
29-
:class:`opentelemetry.trace.Tracer` and the function should return an
30-
instance of a :class:`~opentelemetry.trace.Tracer` (probably of a
31-
derived type).
32-
2. Otherwise, ``OPENTELEMETRY_PYTHON_IMPLEMENTATION_DEFAULT`` is tried
33-
instead.
40+
value, an attempt is made to import a module with that name and use a
41+
factory function named ``get_opentelemetry_implementation`` in it.
42+
2. Otherwise, the same is tried with the environment
43+
variable ``OPENTELEMETRY_PYTHON_IMPLEMENTATION_DEFAULT``.
3444
3. Otherwise, if a :samp:`set_preferred_{<type>}_implementation` was
35-
called, the callback set there is used.
45+
called (e.g.
46+
:func:`opentelemetry.trace.set_preferred_tracer_implementation`), the
47+
callback set there is used (that is, the environment variables override
48+
the callback set in code).
3649
4. Otherwise, if :func:`set_preferred_default_implementation` was called,
3750
the callback set there is used.
3851
5. Otherwise, an attempt is made to import and use the OpenTelemetry SDK.
@@ -42,6 +55,10 @@
4255
If any of the above steps fails (e.g., a module is loaded but does not define
4356
the required function or a module name is set but the module fails to load),
4457
the search immediatelly skips to the last step.
58+
59+
Note that the first two steps (those that query environment variables) are
60+
skipped if :data:`sys.flags` has ``ignore_environment`` set (which usually
61+
means that the Python interpreter was invoked with the ``-E`` or ``-I`` flag).
4562
"""
4663

4764
from typing import Type, TypeVar, Optional, Callable
@@ -54,14 +71,14 @@
5471
# "Untrusted" because this is usually user-provided and we don't trust the user
5572
# to really return a _T: by using object, mypy forces us to check/cast
5673
# explicitly.
57-
_UntrustedImplFactory = Callable[[Type[_T]], object]
74+
_UntrustedImplFactory = Callable[[Type[_T]], Optional[object]]
5875

5976

6077
# This would be the normal ImplementationFactory which would be used to
6178
# annotate setters, were it not for https://github.com/python/mypy/issues/7092
6279
# Once that bug is resolved, setters should use this instead of duplicating the
6380
# code.
64-
#ImplementationFactory = Callable[[Type[_T]], _T]
81+
#ImplementationFactory = Callable[[Type[_T]], Optional[_T]]
6582

6683
_DEFAULT_IMPLEMENTATION_MODNAME = (
6784
'opentelemetry.sdk.internal.implementation_impl')
@@ -136,7 +153,9 @@ def _try_load_configured_impl(
136153

137154
# Public to other opentelemetry-api modules
138155
def _load_impl(
139-
api_type: Type[_T], factory: Optional[Callable[[Type[_T]], _T]]) -> _T:
156+
api_type: Type[_T],
157+
factory: Optional[Callable[[Type[_T]], Optional[_T]]]
158+
) -> _T:
140159
"""Tries to load a configured implementation, if unsuccessful, returns a
141160
fast no-op implemenation that is always available.
142161
"""
@@ -147,8 +166,8 @@ def _load_impl(
147166
return result
148167

149168
def set_preferred_default_implementation(
150-
implementation_module: _UntrustedImplFactory) -> None:
151-
"""Sets a callback that may be queried for any implementation object. See
152-
the module docs for more details."""
169+
implementation_factory: _UntrustedImplFactory) -> None:
170+
"""Sets a factory function that may be called for any implementation
171+
object. See the :ref:`module docs <loader-factory>` for more details."""
153172
global _DEFAULT_FACTORY #pylint:disable=global-statement
154-
_DEFAULT_FACTORY = implementation_module
173+
_DEFAULT_FACTORY = implementation_factory

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

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,8 @@ class TraceState(typing.Dict[str, str]):
251251

252252

253253
_TRACER: typing.Optional[Tracer] = None
254-
_TRACER_FACTORY: \
255-
typing.Optional[typing.Callable[[typing.Type[Tracer]], Tracer]] = None
254+
_TRACER_FACTORY: typing.Optional[
255+
typing.Callable[[typing.Type[Tracer]], typing.Optional[Tracer]]] = None
256256

257257
def tracer() -> Tracer:
258258
"""Gets the current global :class:`~.Tracer` object.
@@ -268,16 +268,18 @@ def tracer() -> Tracer:
268268
return _TRACER
269269

270270
def set_preferred_tracer_implementation(
271-
factory: typing.Callable[[typing.Type[Tracer]], Tracer]) -> None:
272-
"""Sets a callback which to query for the tracer implementation.
271+
factory: typing.Callable[
272+
[typing.Type[Tracer]], typing.Optional[Tracer]]
273+
) -> None:
274+
"""Sets a factory function which may be used to create the tracer
275+
implementation.
273276
274277
See :mod:`opentelemetry.loader` for details.
275278
276279
This function may not be called after a tracer is already loaded.
277280
278281
Args:
279-
factory: A function that, when called with the :class:`Tracer` type
280-
as an argument, returns an instance of :class:`Tracer`.
282+
factory: Callback that should create a new :class:`Tracer` instance.
281283
"""
282284

283285
global _TRACER_FACTORY #pylint:disable=global-statement

0 commit comments

Comments
 (0)