diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000000..6f2257aba5 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,5 @@ +[run] +omit = + */tests/* + */setup.py + */gen/* diff --git a/.gitignore b/.gitignore index c9acc31940..473ef20a4a 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ venv*/ pip-log.txt # Unit test / coverage reports +coverage.xml .coverage .nox .tox diff --git a/.travis.yml b/.travis.yml index 64eebc3621..f8c01c80be 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,3 +19,7 @@ install: script: - tox + +after_success: + - pip install codecov + - codecov -v diff --git a/opentelemetry-api/src/opentelemetry/context/async_context.py b/opentelemetry-api/src/opentelemetry/context/async_context.py index e7337d103f..267059fb31 100644 --- a/opentelemetry-api/src/opentelemetry/context/async_context.py +++ b/opentelemetry-api/src/opentelemetry/context/async_context.py @@ -12,32 +12,34 @@ # See the License for the specific language governing permissions and # limitations under the License. -import typing # pylint: disable=unused-import -from contextvars import ContextVar +try: + from contextvars import ContextVar +except ImportError: + pass +else: + import typing # pylint: disable=unused-import + from . import base_context -from . import base_context + class AsyncRuntimeContext(base_context.BaseRuntimeContext): + class Slot(base_context.BaseRuntimeContext.Slot): + def __init__(self, name: str, default: object): + # pylint: disable=super-init-not-called + self.name = name + self.contextvar = ContextVar(name) # type: ContextVar[object] + self.default = base_context.wrap_callable( + default + ) # type: typing.Callable[..., object] + def clear(self) -> None: + self.contextvar.set(self.default()) -class AsyncRuntimeContext(base_context.BaseRuntimeContext): - class Slot(base_context.BaseRuntimeContext.Slot): - def __init__(self, name: str, default: "object"): - # pylint: disable=super-init-not-called - self.name = name - self.contextvar = ContextVar(name) # type: ContextVar[object] - self.default = base_context.wrap_callable( - default - ) # type: typing.Callable[..., object] + def get(self) -> object: + try: + return self.contextvar.get() + except LookupError: + value = self.default() + self.set(value) + return value - def clear(self) -> None: - self.contextvar.set(self.default()) - - def get(self) -> "object": - try: - return self.contextvar.get() - except LookupError: - value = self.default() - self.set(value) - return value - - def set(self, value: "object") -> None: - self.contextvar.set(value) + def set(self, value: object) -> None: + self.contextvar.set(value) diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000000..a71d000b56 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +addopts = -rs -v diff --git a/scripts/coverage.sh b/scripts/coverage.sh new file mode 100755 index 0000000000..bddf39a90c --- /dev/null +++ b/scripts/coverage.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +set -e + +function cov { + pytest \ + --ignore-glob=*/setup.py \ + --cov ${1} \ + --cov-append \ + --cov-branch \ + --cov-report='' \ + ${1} +} + + +coverage erase + +cov opentelemetry-api +cov opentelemetry-sdk +cov ext/opentelemetry-ext-http-requests +cov ext/opentelemetry-ext-jaeger +cov ext/opentelemetry-ext-opentracing-shim +cov ext/opentelemetry-ext-wsgi +cov examples/opentelemetry-example-app + +coverage report +coverage xml diff --git a/tox.ini b/tox.ini index e30cb1a14b..1791978227 100644 --- a/tox.ini +++ b/tox.ini @@ -4,6 +4,11 @@ skip_missing_interpreters = True envlist = py3{4,5,6,7,8}-test-{api,sdk,example-app,ext-wsgi,ext-http-requests,ext-jaeger,opentracing-shim} pypy3-test-{api,sdk,example-app,ext-wsgi,ext-http-requests,ext-jaeger,opentracing-shim} + py3{4,5,6,7,8}-coverage + + ; Coverage is temporarily disabled for pypy3 due to the pytest bug. + ; pypy3-coverage + lint py37-tracecontext py37-{mypy,mypyinstalled} @@ -15,6 +20,8 @@ python = [testenv] deps = + test: pytest + coverage: pytest-cov mypy,mypyinstalled: mypy~=0.740 setenv = @@ -45,12 +52,24 @@ commands_pre = jaeger: pip install {toxinidir}/ext/opentelemetry-ext-jaeger opentracing-shim: pip install {toxinidir}/opentelemetry-sdk {toxinidir}/ext/opentelemetry-ext-opentracing-shim +; In order to get a healthy coverage report, +; we have to install packages in editable mode. + coverage: pip install -e {toxinidir}/opentelemetry-api + coverage: pip install -e {toxinidir}/opentelemetry-sdk + coverage: pip install -e {toxinidir}/ext/opentelemetry-ext-azure-monitor + coverage: pip install -e {toxinidir}/ext/opentelemetry-ext-http-requests + coverage: pip install -e {toxinidir}/ext/opentelemetry-ext-jaeger + coverage: pip install -e {toxinidir}/ext/opentelemetry-ext-opentracing-shim + coverage: pip install -e {toxinidir}/ext/opentelemetry-ext-wsgi + coverage: pip install -e {toxinidir}/examples/opentelemetry-example-app + ; Using file:// here because otherwise tox invokes just "pip install ; opentelemetry-api", leading to an error mypyinstalled: pip install file://{toxinidir}/opentelemetry-api/ commands = - test: python -m unittest discover + test: pytest + coverage: {toxinidir}/scripts/coverage.sh mypy: mypy --namespace-packages opentelemetry-api/src/opentelemetry/ ; For test code, we don't want to enforce the full mypy strictness