Add type checker (#3116)
This commit is contained in:
		
							parent
							
								
									8406e2e789
								
							
						
					
					
						commit
						406707b2bd
					
				|  | @ -152,3 +152,21 @@ jobs: | ||||||
| 
 | 
 | ||||||
|       - name: Run tests |       - name: Run tests | ||||||
|         run: tox -e ruff |         run: tox -e ruff | ||||||
|  | 
 | ||||||
|  |   typecheck: | ||||||
|  |     name: typecheck | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     steps: | ||||||
|  |       - name: Checkout repo @ SHA - ${{ github.sha }} | ||||||
|  |         uses: actions/checkout@v4 | ||||||
|  | 
 | ||||||
|  |       - name: Set up Python 3.11 | ||||||
|  |         uses: actions/setup-python@v5 | ||||||
|  |         with: | ||||||
|  |           python-version: "3.11" | ||||||
|  | 
 | ||||||
|  |       - name: Install tox | ||||||
|  |         run: pip install tox | ||||||
|  | 
 | ||||||
|  |       - name: Run tests | ||||||
|  |         run: tox -e typecheck | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| pylint==3.0.2 | pylint==3.0.2 | ||||||
| httpretty==1.1.4 | httpretty==1.1.4 | ||||||
| mypy==0.931 | pyright==v1.1.390 | ||||||
| sphinx==7.1.2 | sphinx==7.1.2 | ||||||
| sphinx-rtd-theme==2.0.0rc4 | sphinx-rtd-theme==2.0.0rc4 | ||||||
| sphinx-autodoc-typehints==1.25.2 | sphinx-autodoc-typehints==1.25.2 | ||||||
|  |  | ||||||
|  | @ -35,17 +35,29 @@ context attached, and this context will be re-activated in the thread's | ||||||
| run method or the executor's worker thread." | run method or the executor's worker thread." | ||||||
| """ | """ | ||||||
| 
 | 
 | ||||||
|  | from __future__ import annotations | ||||||
|  | 
 | ||||||
| import threading | import threading | ||||||
| from concurrent import futures | from concurrent import futures | ||||||
| from typing import Collection | from typing import TYPE_CHECKING, Any, Callable, Collection | ||||||
| 
 | 
 | ||||||
| from wrapt import wrap_function_wrapper | from wrapt import ( | ||||||
|  |     wrap_function_wrapper,  # type: ignore[reportUnknownVariableType] | ||||||
|  | ) | ||||||
| 
 | 
 | ||||||
| from opentelemetry import context | from opentelemetry import context | ||||||
| from opentelemetry.instrumentation.instrumentor import BaseInstrumentor | from opentelemetry.instrumentation.instrumentor import BaseInstrumentor | ||||||
| from opentelemetry.instrumentation.threading.package import _instruments | from opentelemetry.instrumentation.threading.package import _instruments | ||||||
| from opentelemetry.instrumentation.utils import unwrap | from opentelemetry.instrumentation.utils import unwrap | ||||||
| 
 | 
 | ||||||
|  | if TYPE_CHECKING: | ||||||
|  |     from typing import Protocol, TypeVar | ||||||
|  | 
 | ||||||
|  |     R = TypeVar("R") | ||||||
|  | 
 | ||||||
|  |     class HasOtelContext(Protocol): | ||||||
|  |         _otel_context: context.Context | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class ThreadingInstrumentor(BaseInstrumentor): | class ThreadingInstrumentor(BaseInstrumentor): | ||||||
|     __WRAPPER_START_METHOD = "start" |     __WRAPPER_START_METHOD = "start" | ||||||
|  | @ -55,12 +67,12 @@ class ThreadingInstrumentor(BaseInstrumentor): | ||||||
|     def instrumentation_dependencies(self) -> Collection[str]: |     def instrumentation_dependencies(self) -> Collection[str]: | ||||||
|         return _instruments |         return _instruments | ||||||
| 
 | 
 | ||||||
|     def _instrument(self, **kwargs): |     def _instrument(self, **kwargs: Any): | ||||||
|         self._instrument_thread() |         self._instrument_thread() | ||||||
|         self._instrument_timer() |         self._instrument_timer() | ||||||
|         self._instrument_thread_pool() |         self._instrument_thread_pool() | ||||||
| 
 | 
 | ||||||
|     def _uninstrument(self, **kwargs): |     def _uninstrument(self, **kwargs: Any): | ||||||
|         self._uninstrument_thread() |         self._uninstrument_thread() | ||||||
|         self._uninstrument_timer() |         self._uninstrument_timer() | ||||||
|         self._uninstrument_thread_pool() |         self._uninstrument_thread_pool() | ||||||
|  | @ -117,12 +129,22 @@ class ThreadingInstrumentor(BaseInstrumentor): | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def __wrap_threading_start(call_wrapped, instance, args, kwargs): |     def __wrap_threading_start( | ||||||
|  |         call_wrapped: Callable[[], None], | ||||||
|  |         instance: HasOtelContext, | ||||||
|  |         args: ..., | ||||||
|  |         kwargs: ..., | ||||||
|  |     ) -> None: | ||||||
|         instance._otel_context = context.get_current() |         instance._otel_context = context.get_current() | ||||||
|         return call_wrapped(*args, **kwargs) |         return call_wrapped(*args, **kwargs) | ||||||
| 
 | 
 | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def __wrap_threading_run(call_wrapped, instance, args, kwargs): |     def __wrap_threading_run( | ||||||
|  |         call_wrapped: Callable[..., R], | ||||||
|  |         instance: HasOtelContext, | ||||||
|  |         args: tuple[Any, ...], | ||||||
|  |         kwargs: dict[str, Any], | ||||||
|  |     ) -> R: | ||||||
|         token = None |         token = None | ||||||
|         try: |         try: | ||||||
|             token = context.attach(instance._otel_context) |             token = context.attach(instance._otel_context) | ||||||
|  | @ -131,12 +153,17 @@ class ThreadingInstrumentor(BaseInstrumentor): | ||||||
|             context.detach(token) |             context.detach(token) | ||||||
| 
 | 
 | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def __wrap_thread_pool_submit(call_wrapped, instance, args, kwargs): |     def __wrap_thread_pool_submit( | ||||||
|  |         call_wrapped: Callable[..., R], | ||||||
|  |         instance: futures.ThreadPoolExecutor, | ||||||
|  |         args: tuple[Callable[..., Any], ...], | ||||||
|  |         kwargs: dict[str, Any], | ||||||
|  |     ) -> R: | ||||||
|         # obtain the original function and wrapped kwargs |         # obtain the original function and wrapped kwargs | ||||||
|         original_func = args[0] |         original_func = args[0] | ||||||
|         otel_context = context.get_current() |         otel_context = context.get_current() | ||||||
| 
 | 
 | ||||||
|         def wrapped_func(*func_args, **func_kwargs): |         def wrapped_func(*func_args: Any, **func_kwargs: Any) -> R: | ||||||
|             token = None |             token = None | ||||||
|             try: |             try: | ||||||
|                 token = context.attach(otel_context) |                 token = context.attach(otel_context) | ||||||
|  | @ -145,5 +172,5 @@ class ThreadingInstrumentor(BaseInstrumentor): | ||||||
|                 context.detach(token) |                 context.detach(token) | ||||||
| 
 | 
 | ||||||
|         # replace the original function with the wrapped function |         # replace the original function with the wrapped function | ||||||
|         new_args = (wrapped_func,) + args[1:] |         new_args: tuple[Callable[..., Any], ...] = (wrapped_func,) + args[1:] | ||||||
|         return call_wrapped(*new_args, **kwargs) |         return call_wrapped(*new_args, **kwargs) | ||||||
|  |  | ||||||
|  | @ -39,3 +39,19 @@ known-third-party = [ | ||||||
|   "opencensus", |   "opencensus", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | # https://github.com/microsoft/pyright/blob/main/docs/configuration.md#type-check-rule-overrides | ||||||
|  | [tool.pyright] | ||||||
|  | typeCheckingMode = "strict" | ||||||
|  | reportUnnecessaryTypeIgnoreComment = true | ||||||
|  | reportMissingTypeStubs = false | ||||||
|  | pythonVersion = "3.8" | ||||||
|  | reportPrivateUsage = false  # Ignore private attributes added by instrumentation packages. | ||||||
|  | # Add progressively instrumentation packages here. | ||||||
|  | include = [ | ||||||
|  |   "instrumentation/opentelemetry-instrumentation-threading/**/*.py" | ||||||
|  | ] | ||||||
|  | # We should also add type hints to the test suite - It helps on finding bugs. | ||||||
|  | # We are excluding for now because it's easier, and more important to add to the instrumentation packages. | ||||||
|  | exclude = [ | ||||||
|  |   "instrumentation/opentelemetry-instrumentation-threading/tests/**", | ||||||
|  | ] | ||||||
|  |  | ||||||
							
								
								
									
										12
									
								
								tox.ini
								
								
								
								
							
							
						
						
									
										12
									
								
								tox.ini
								
								
								
								
							|  | @ -404,6 +404,7 @@ envlist = | ||||||
|     generate-workflows |     generate-workflows | ||||||
|     shellcheck |     shellcheck | ||||||
|     ruff |     ruff | ||||||
|  |     typecheck | ||||||
| 
 | 
 | ||||||
| [testenv] | [testenv] | ||||||
| test_deps = | test_deps = | ||||||
|  | @ -677,7 +678,6 @@ deps = | ||||||
|   util-http: -r {toxinidir}/util/opentelemetry-util-http/test-requirements.txt |   util-http: -r {toxinidir}/util/opentelemetry-util-http/test-requirements.txt | ||||||
|   util-http: {toxinidir}/util/opentelemetry-util-http |   util-http: {toxinidir}/util/opentelemetry-util-http | ||||||
|   ; FIXME: add coverage testing |   ; FIXME: add coverage testing | ||||||
|   ; FIXME: add mypy testing |  | ||||||
| allowlist_externals = | allowlist_externals = | ||||||
|   sh |   sh | ||||||
| 
 | 
 | ||||||
|  | @ -986,3 +986,13 @@ deps = | ||||||
|   pre-commit |   pre-commit | ||||||
| commands = | commands = | ||||||
|   pre-commit run --color=always --all-files {posargs} |   pre-commit run --color=always --all-files {posargs} | ||||||
|  | 
 | ||||||
|  | [testenv:typecheck] | ||||||
|  | deps = | ||||||
|  |   -c {toxinidir}/dev-requirements.txt | ||||||
|  |   pyright | ||||||
|  |   {[testenv]test_deps} | ||||||
|  |   {toxinidir}/opentelemetry-instrumentation | ||||||
|  |   {toxinidir}/util/opentelemetry-util-http | ||||||
|  | commands = | ||||||
|  |   pyright | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue