diff --git a/.pylintrc b/.pylintrc
index cf61fde78dd..5b0f7862526 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -28,7 +28,7 @@ limit-inference-results=100
 
 # List of plugins (as comma separated values of python modules names) to load,
 # usually to register additional checkers.
-load-plugins=
+load-plugins=pylint.extensions.no_self_use
 
 # Pickle collected data for later comparisons.
 persistent=yes
@@ -68,7 +68,6 @@ disable=missing-docstring,
       duplicate-code,
       ungrouped-imports, # Leave this up to isort
       wrong-import-order, # Leave this up to isort
-      bad-continuation, # Leave this up to black
       line-too-long, # Leave this up to black
       exec-used,
       super-with-arguments, # temp-pylint-upgrade
@@ -76,6 +75,7 @@ disable=missing-docstring,
       raise-missing-from, # temp-pylint-upgrade
       unused-argument, # temp-pylint-upgrade
       redefined-builtin,
+      cyclic-import,
 
 # Enable the message, report, category or checker with the given id(s). You can
 # either give multiple identifier separated by comma (,) or put this option
@@ -263,13 +263,6 @@ max-line-length=79
 # Maximum number of lines in a module.
 max-module-lines=1000
 
-# List of optional constructs for which whitespace checking is disabled. `dict-
-# separator` is used to allow tabulation in dicts, etc.: {1  : 1,\n222: 2}.
-# `trailing-comma` allows a space between comma and closing bracket: (a, ).
-# `empty-line` allows space-only lines.
-no-space-check=trailing-comma,
-               dict-separator
-
 # Allow the body of a class to be on the same line as the declaration if body
 # contains single statement.
 single-line-class-stmt=no
diff --git a/dev-requirements.txt b/dev-requirements.txt
index 732acd8b2ef..613b5984c15 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -1,21 +1,15 @@
-pylint==2.11.0
-flake8~=3.7
-isort~=5.8
-black~=22.3.0
-httpretty~=1.0
+pylint==3.0.2
+flake8==6.1.0
+isort==5.12.0
+black==22.3.0
+httpretty==1.1.4
 mypy==0.931
-sphinx~=3.5.4
-sphinx-rtd-theme~=0.5
-sphinx-autodoc-typehints~=1.12.0
+sphinx==7.1.2
+sphinx-rtd-theme==2.0.0rc4
+sphinx-autodoc-typehints==1.25.2
 pytest==7.1.3
-pytest-cov>=2.8
-readme-renderer~=24.0
-# This version of grpcio-tools ships with protoc 3.19.4 which appears to be compatible with
-# both protobuf 3.19.x and 4.x (see https://github.com/protocolbuffers/protobuf/issues/11123).
-# Bump this version with caution to preserve compatibility with protobuf 3.
-# https://github.com/open-telemetry/opentelemetry-python/blob/main/opentelemetry-proto/pyproject.toml#L28
-grpcio-tools==1.48.1
-mypy-protobuf~=3.0.0
+pytest-cov==4.1.0
+readme-renderer==42.0
 # temporary fix. we should update the jinja, flask deps
 # See https://github.com/pallets/markupsafe/issues/282
 # breaking change introduced in markupsafe causes jinja, flask to break
@@ -24,3 +18,7 @@ bleach==4.1.0 # This dependency was updated to a breaking version.
 codespell==2.1.0
 requests==2.31.0
 ruamel.yaml==0.17.21
+asgiref==3.7.2
+psutil==5.9.6
+GitPython==3.1.40
+flaky==3.7.0
diff --git a/docs-requirements.txt b/docs-requirements.txt
index c167ab785d1..dcbcd41bfa7 100644
--- a/docs-requirements.txt
+++ b/docs-requirements.txt
@@ -1,23 +1,24 @@
-sphinx~=3.5.4
-sphinx-rtd-theme~=0.5
-sphinx-autodoc-typehints
+sphinx==7.1.2
+sphinx-rtd-theme==2.0.0rc4
+sphinx-autodoc-typehints==1.25.2
 # used to generate docs for the website
-sphinx-jekyll-builder
+sphinx-jekyll-builder==0.3.0
 
 # Need to install the api/sdk in the venv for autodoc. Modifying sys.path
 # doesn't work for pkg_resources.
 ./opentelemetry-api
 ./opentelemetry-semantic-conventions
 ./opentelemetry-sdk
+./shim/opentelemetry-opencensus-shim
+./shim/opentelemetry-opentracing-shim
 
 # Required by instrumentation and exporter packages
-ddtrace>=0.34.0
 grpcio~=1.27
-Deprecated>=1.2.6
-django>=2.2
+Deprecated~=1.2
+django~=4.2
 flask~=1.0
 opentracing~=2.2.0
-thrift>=0.10.0
+thrift~=0.10
 wrapt>=1.0.0,<2.0.0
 # temporary fix. we should update the jinja, flask deps
 # See https://github.com/pallets/markupsafe/issues/282
diff --git a/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/send.py b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/send.py
index 9ddc6d7b27e..0e3a411de6b 100644
--- a/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/send.py
+++ b/exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/send.py
@@ -125,7 +125,7 @@ def __init__(self, thrift_url="", auth=None, timeout_in_millis=None):
         if auth is not None:
             auth_header = f"{auth[0]}:{auth[1]}"
             decoded = base64.b64encode(auth_header.encode()).decode("ascii")
-            basic_auth = dict(Authorization=f"Basic {decoded}")
+            basic_auth = {"Authorization": f"Basic {decoded}"}
             self.http_transport.setCustomHeaders(basic_auth)
 
     def submit(self, batch: jaeger.Batch):
diff --git a/exporter/opentelemetry-exporter-jaeger/tests/__init__.py b/exporter/opentelemetry-exporter-jaeger/tests/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/exporter/opentelemetry-exporter-otlp-proto-common/pyproject.toml b/exporter/opentelemetry-exporter-otlp-proto-common/pyproject.toml
index 4751da63a47..bef34ed82bb 100644
--- a/exporter/opentelemetry-exporter-otlp-proto-common/pyproject.toml
+++ b/exporter/opentelemetry-exporter-otlp-proto-common/pyproject.toml
@@ -30,6 +30,9 @@ dependencies = [
   "backoff >= 1.10.0, < 3.0.0; python_version>='3.7'",
 ]
 
+[project.optional-dependencies]
+test = []
+
 [project.urls]
 Homepage = "https://github.com/open-telemetry/opentelemetry-python/tree/main/exporter/opentelemetry-exporter-otlp-proto-common"
 
diff --git a/exporter/opentelemetry-exporter-otlp-proto-common/tests/__init__.py b/exporter/opentelemetry-exporter-otlp-proto-common/tests/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/exporter/opentelemetry-exporter-otlp-proto-http/tests/__init__.py b/exporter/opentelemetry-exporter-otlp-proto-http/tests/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/exporter/opentelemetry-exporter-otlp-proto-http/tests/metrics/__init__.py b/exporter/opentelemetry-exporter-otlp-proto-http/tests/metrics/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/exporter/opentelemetry-exporter-otlp/pyproject.toml b/exporter/opentelemetry-exporter-otlp/pyproject.toml
index cfd8843cab4..707b8c94556 100644
--- a/exporter/opentelemetry-exporter-otlp/pyproject.toml
+++ b/exporter/opentelemetry-exporter-otlp/pyproject.toml
@@ -30,6 +30,9 @@ dependencies = [
   "opentelemetry-exporter-otlp-proto-http == 1.22.0.dev",
 ]
 
+[project.optional-dependencies]
+test = []
+
 [project.entry-points.opentelemetry_logs_exporter]
 otlp = "opentelemetry.exporter.otlp.proto.grpc._log_exporter:OTLPLogExporter"
 
diff --git a/exporter/opentelemetry-exporter-otlp/tests/__init__.py b/exporter/opentelemetry-exporter-otlp/tests/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/exporter/opentelemetry-exporter-zipkin/tests/__init__.py b/exporter/opentelemetry-exporter-zipkin/tests/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/gen-requirements.txt b/gen-requirements.txt
new file mode 100644
index 00000000000..88f8817b2df
--- /dev/null
+++ b/gen-requirements.txt
@@ -0,0 +1,6 @@
+# This version of grpcio-tools ships with protoc 3.19.4 which appears to be compatible with
+# both protobuf 3.19.x and 4.x (see https://github.com/protocolbuffers/protobuf/issues/11123).
+# Bump this version with caution to preserve compatibility with protobuf 3.
+# https://github.com/open-telemetry/opentelemetry-python/blob/main/opentelemetry-proto/pyproject.toml#L28
+grpcio-tools==1.48.1
+mypy-protobuf~=3.0.0
diff --git a/opentelemetry-api/src/opentelemetry/_logs/_internal/__init__.py b/opentelemetry-api/src/opentelemetry/_logs/_internal/__init__.py
index 4c25eed0748..e67f28439b6 100644
--- a/opentelemetry-api/src/opentelemetry/_logs/_internal/__init__.py
+++ b/opentelemetry-api/src/opentelemetry/_logs/_internal/__init__.py
@@ -177,7 +177,7 @@ def get_logger_provider() -> LoggerProvider:
     """Gets the current global :class:`~.LoggerProvider` object."""
     global _LOGGER_PROVIDER  # pylint: disable=global-statement
     if _LOGGER_PROVIDER is None:
-        if _OTEL_PYTHON_LOGGER_PROVIDER not in environ.keys():
+        if _OTEL_PYTHON_LOGGER_PROVIDER not in environ:
             # TODO: return proxy
             _LOGGER_PROVIDER = NoOpLoggerProvider()
             return _LOGGER_PROVIDER
diff --git a/opentelemetry-api/src/opentelemetry/metrics/_internal/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/_internal/__init__.py
index aad76b33a72..dc1e76c8ae8 100644
--- a/opentelemetry-api/src/opentelemetry/metrics/_internal/__init__.py
+++ b/opentelemetry-api/src/opentelemetry/metrics/_internal/__init__.py
@@ -75,6 +75,7 @@
 _logger = getLogger(__name__)
 
 
+# pylint: disable=invalid-name
 _ProxyInstrumentT = Union[
     _ProxyCounter,
     _ProxyHistogram,
@@ -760,7 +761,7 @@ def get_meter_provider() -> MeterProvider:
     """Gets the current global :class:`~.MeterProvider` object."""
 
     if _METER_PROVIDER is None:
-        if OTEL_PYTHON_METER_PROVIDER not in environ.keys():
+        if OTEL_PYTHON_METER_PROVIDER not in environ:
             return _PROXY_METER_PROVIDER
 
         meter_provider: MeterProvider = _load_provider(  # type: ignore
diff --git a/opentelemetry-api/src/opentelemetry/metrics/_internal/instrument.py b/opentelemetry-api/src/opentelemetry/metrics/_internal/instrument.py
index 54b2fb7597e..b02a15005c3 100644
--- a/opentelemetry-api/src/opentelemetry/metrics/_internal/instrument.py
+++ b/opentelemetry-api/src/opentelemetry/metrics/_internal/instrument.py
@@ -55,6 +55,7 @@ class CallbackOptions:
 
 
 InstrumentT = TypeVar("InstrumentT", bound="Instrument")
+# pylint: disable=invalid-name
 CallbackT = Union[
     Callable[[CallbackOptions], Iterable[Observation]],
     Generator[Iterable[Observation], CallbackOptions, None],
diff --git a/opentelemetry-api/src/opentelemetry/propagators/textmap.py b/opentelemetry-api/src/opentelemetry/propagators/textmap.py
index afadd35000b..42f1124f36d 100644
--- a/opentelemetry-api/src/opentelemetry/propagators/textmap.py
+++ b/opentelemetry-api/src/opentelemetry/propagators/textmap.py
@@ -18,6 +18,7 @@
 from opentelemetry.context.context import Context
 
 CarrierT = typing.TypeVar("CarrierT")
+# pylint: disable=invalid-name
 CarrierValT = typing.Union[typing.List[str], str]
 
 
diff --git a/opentelemetry-api/tests/context/test_contextvars_context.py b/opentelemetry-api/tests/context/test_contextvars_context.py
index dc27e271908..e9af3107d84 100644
--- a/opentelemetry-api/tests/context/test_contextvars_context.py
+++ b/opentelemetry-api/tests/context/test_contextvars_context.py
@@ -17,10 +17,12 @@
 from opentelemetry import context
 from opentelemetry.context.contextvars_context import ContextVarsRuntimeContext
 
-from .base_context import ContextTestCases
+# pylint: disable=import-error,no-name-in-module
+from tests.context.base_context import ContextTestCases
 
 
 class TestContextVarsContext(ContextTestCases.BaseTest):
+    # pylint: disable=invalid-name
     def setUp(self) -> None:
         super().setUp()
         self.mock_runtime = patch.object(
@@ -30,6 +32,7 @@ def setUp(self) -> None:
         )
         self.mock_runtime.start()
 
+    # pylint: disable=invalid-name
     def tearDown(self) -> None:
         super().tearDown()
         self.mock_runtime.stop()
diff --git a/opentelemetry-api/tests/trace/propagation/test_tracecontexthttptextformat.py b/opentelemetry-api/tests/trace/propagation/test_tracecontexthttptextformat.py
index ac57b5c919e..7fefd8dea67 100644
--- a/opentelemetry-api/tests/trace/propagation/test_tracecontexthttptextformat.py
+++ b/opentelemetry-api/tests/trace/propagation/test_tracecontexthttptextformat.py
@@ -39,7 +39,7 @@ def test_no_traceparent_header(self):
         If no traceparent header is received, the vendor creates a new
         trace-id and parent-id that represents the current request.
         """
-        output = {}  # type:typing.Dict[str, typing.List[str]]
+        output: typing.Dict[str, typing.List[str]] = {}
         span = trace.get_current_span(FORMAT.extract(output))
         self.assertIsInstance(span.get_span_context(), trace.SpanContext)
 
@@ -66,7 +66,7 @@ def test_headers_with_tracestate(self):
             span_context.trace_state, {"foo": "1", "bar": "2", "baz": "3"}
         )
         self.assertTrue(span_context.is_remote)
-        output = {}  # type:typing.Dict[str, str]
+        output: typing.Dict[str, str] = {}
         span = trace.NonRecordingSpan(span_context)
 
         ctx = trace.set_span_in_context(span)
@@ -145,7 +145,7 @@ def test_no_send_empty_tracestate(self):
         Empty and whitespace-only list members are allowed. Vendors MUST accept
         empty tracestate headers but SHOULD avoid sending them.
         """
-        output = {}  # type:typing.Dict[str, str]
+        output: typing.Dict[str, str] = {}
         span = trace.NonRecordingSpan(
             trace.SpanContext(self.TRACE_ID, self.SPAN_ID, is_remote=False)
         )
@@ -177,7 +177,7 @@ def test_format_not_supported(self):
 
     def test_propagate_invalid_context(self):
         """Do not propagate invalid trace context."""
-        output = {}  # type:typing.Dict[str, str]
+        output: typing.Dict[str, str] = {}
         ctx = trace.set_span_in_context(trace.INVALID_SPAN)
         FORMAT.inject(output, context=ctx)
         self.assertFalse("traceparent" in output)
diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py
index 8ccad56c7a1..14140d26b73 100644
--- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py
+++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py
@@ -166,6 +166,10 @@ class BatchLogRecordProcessor(LogRecordProcessor):
     - :envvar:`OTEL_BLRP_EXPORT_TIMEOUT`
     """
 
+    _queue: Deque[LogData]
+    _flush_request: Optional[_FlushRequest]
+    _log_records: List[Optional[LogData]]
+
     def __init__(
         self,
         exporter: LogExporter,
@@ -201,9 +205,7 @@ def __init__(
         self._schedule_delay_millis = schedule_delay_millis
         self._max_export_batch_size = max_export_batch_size
         self._export_timeout_millis = export_timeout_millis
-        self._queue = collections.deque(
-            [], max_queue_size
-        )  # type: Deque[LogData]
+        self._queue = collections.deque([], max_queue_size)
         self._worker_thread = threading.Thread(
             name="OtelBatchLogRecordProcessor",
             target=self.worker,
@@ -211,10 +213,8 @@ def __init__(
         )
         self._condition = threading.Condition(threading.Lock())
         self._shutdown = False
-        self._flush_request = None  # type: Optional[_FlushRequest]
-        self._log_records = [
-            None
-        ] * self._max_export_batch_size  # type: List[Optional[LogData]]
+        self._flush_request = None
+        self._log_records = [None] * self._max_export_batch_size
         self._worker_thread.start()
         # Only available in *nix since py37.
         if hasattr(os, "register_at_fork"):
@@ -236,7 +236,7 @@ def _at_fork_reinit(self):
 
     def worker(self):
         timeout = self._schedule_delay_millis / 1e3
-        flush_request = None  # type: Optional[_FlushRequest]
+        flush_request: Optional[_FlushRequest] = None
         while not self._shutdown:
             with self._condition:
                 if self._shutdown:
diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/environment_variables.py b/opentelemetry-sdk/src/opentelemetry/sdk/environment_variables.py
index dc8f91f600a..a69e451cbb8 100644
--- a/opentelemetry-sdk/src/opentelemetry/sdk/environment_variables.py
+++ b/opentelemetry-sdk/src/opentelemetry/sdk/environment_variables.py
@@ -674,7 +674,7 @@
 
 The :envvar:`OTEL_EXPERIMENTAL_RESOURCE_DETECTORS` is a comma-separated string
 of names of resource detectors. These names must be the same as the names of
-entry points for the `opentelemetry_resource_detector` entry point. This is an
+entry points for the ```opentelemetry_resource_detector``` entry point. This is an
 experimental feature and the name of this variable and its behavior can change
 in a non-backwards compatible way.
 """
diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/aggregation.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/aggregation.py
index 1f6d4c4c13a..62ba091ebfe 100644
--- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/aggregation.py
+++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/aggregation.py
@@ -646,6 +646,7 @@ def aggregate(self, measurement: Measurement) -> None:
 
             # 3. Determine if a change of scale is needed.
             is_rescaling_needed = False
+            low, high = 0, 0
 
             if len(buckets) == 0:
                 buckets.index_start = index
diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/point.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/point.py
index cba37e7fdf1..c30705c59a4 100644
--- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/point.py
+++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/point.py
@@ -170,6 +170,7 @@ def to_json(self, indent=4) -> str:
         )
 
 
+# pylint: disable=invalid-name
 DataT = Union[Sum, Gauge, Histogram]
 DataPointT = Union[NumberDataPoint, HistogramDataPoint]
 
diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py
index dd5bea43d4c..42fcf125bb4 100644
--- a/opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py
+++ b/opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py
@@ -365,11 +365,11 @@ def get_aggregated_resources(
         futures = [executor.submit(detector.detect) for detector in detectors]
         for detector_ind, future in enumerate(futures):
             detector = detectors[detector_ind]
+            detected_resource: Resource = _EMPTY_RESOURCE
             try:
                 detected_resource = future.result(timeout=timeout)
             # pylint: disable=broad-except
             except Exception as ex:
-                detected_resource = _EMPTY_RESOURCE
                 if detector.raise_on_error:
                     raise ex
                 logger.warning(
diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py
index 8897585607a..6dae70b2f6b 100644
--- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py
+++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py
@@ -140,10 +140,12 @@ class SynchronousMultiSpanProcessor(SpanProcessor):
     added.
     """
 
+    _span_processors: Tuple[SpanProcessor, ...]
+
     def __init__(self):
         # use a tuple to avoid race conditions when adding a new span and
         # iterating through it on "on_start" and "on_end".
-        self._span_processors = ()  # type: Tuple[SpanProcessor, ...]
+        self._span_processors = ()
         self._lock = threading.Lock()
 
     def add_span_processor(self, span_processor: SpanProcessor) -> None:
diff --git a/opentelemetry-sdk/tests/trace/test_trace.py b/opentelemetry-sdk/tests/trace/test_trace.py
index 83a4ece5ed7..4150d60d104 100644
--- a/opentelemetry-sdk/tests/trace/test_trace.py
+++ b/opentelemetry-sdk/tests/trace/test_trace.py
@@ -1220,6 +1220,7 @@ def test_record_exception_with_attributes_and_timestamp(self):
         self.assertEqual(1604238587112021089, exception_event.timestamp)
 
     def test_record_exception_context_manager(self):
+        span = None
         try:
             with self.tracer.start_as_current_span("span") as span:
                 raise RuntimeError("example error")
diff --git a/pyproject.toml b/pyproject.toml
index 27d530a7f65..405792011e3 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -5,6 +5,9 @@ exclude = '''
   /(  # generated files
     .tox|
     venv|
+    venv.*|
+    .venv.*|
+    target.*|
     .*/build/lib/.*|
     exporter/opentelemetry-exporter-jaeger-proto-grpc/src/opentelemetry/exporter/jaeger/proto/grpc/gen|
     exporter/opentelemetry-exporter-jaeger-thrift/src/opentelemetry/exporter/jaeger/thrift/gen|
diff --git a/scripts/proto_codegen.sh b/scripts/proto_codegen.sh
index 53d8ad8fc72..26fb8b1ee85 100755
--- a/scripts/proto_codegen.sh
+++ b/scripts/proto_codegen.sh
@@ -32,7 +32,7 @@ echo "Creating temporary virtualenv at $venv_dir using $(python3 --version)"
 python3 -m venv $venv_dir
 source $venv_dir/bin/activate
 python -m pip install \
-    -c $repo_root/dev-requirements.txt \
+    -c $repo_root/gen-requirements.txt \
     grpcio-tools mypy-protobuf
 echo 'python -m grpc_tools.protoc --version'
 python -m grpc_tools.protoc --version
diff --git a/scripts/update_sha.py b/scripts/update_sha.py
index c7da2e1a546..429470c0554 100644
--- a/scripts/update_sha.py
+++ b/scripts/update_sha.py
@@ -25,7 +25,7 @@
 
 def get_sha(branch):
     url = API_URL + branch
-    response = requests.get(url)
+    response = requests.get(url, timeout=15)
     response.raise_for_status()
     return response.json()["sha"]
 
diff --git a/shim/opentelemetry-opencensus-shim/tests/__init__.py b/shim/opentelemetry-opencensus-shim/tests/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/shim/opentelemetry-opentracing-shim/src/opentelemetry/shim/opentracing_shim/__init__.py b/shim/opentelemetry-opentracing-shim/src/opentelemetry/shim/opentracing_shim/__init__.py
index 7d29a3412f2..8fd72da9720 100644
--- a/shim/opentelemetry-opentracing-shim/src/opentelemetry/shim/opentracing_shim/__init__.py
+++ b/shim/opentelemetry-opentracing-shim/src/opentelemetry/shim/opentracing_shim/__init__.py
@@ -387,6 +387,7 @@ def from_context_manager(cls, manager: "ScopeManagerShim", span_cm):
                 :meth:`opentelemetry.trace.use_span`.
         """
 
+        # pylint: disable=unnecessary-dunder-call
         otel_span = span_cm.__enter__()
         span_context = SpanContextShim(otel_span.get_span_context())
         span = SpanShim(manager.tracer, span_context, otel_span)
diff --git a/shim/opentelemetry-opentracing-shim/tests/testbed/test_multiple_callbacks/test_threads.py b/shim/opentelemetry-opentracing-shim/tests/testbed/test_multiple_callbacks/test_threads.py
index 6e8b405ccee..d94f834e513 100644
--- a/shim/opentelemetry-opentracing-shim/tests/testbed/test_multiple_callbacks/test_threads.py
+++ b/shim/opentelemetry-opentracing-shim/tests/testbed/test_multiple_callbacks/test_threads.py
@@ -55,6 +55,7 @@ def test_main(self):
     def task(self, interval, parent_span):
         logger.info("Starting task")
 
+        scope = None
         try:
             scope = self.tracer.scope_manager.activate(parent_span, False)
             with self.tracer.start_active_span("task"):
diff --git a/tests/opentelemetry-test-utils/src/opentelemetry/test/test_base.py b/tests/opentelemetry-test-utils/src/opentelemetry/test/test_base.py
index 6a65e112f77..f9ac2dfc193 100644
--- a/tests/opentelemetry-test-utils/src/opentelemetry/test/test_base.py
+++ b/tests/opentelemetry-test-utils/src/opentelemetry/test/test_base.py
@@ -186,7 +186,9 @@ def is_data_points_equal(
         data_point: DataPointT,
         est_value_delta: Optional[float] = 0,
     ):
-        if type(expected_data_point) != type(data_point) or not isinstance(
+        if type(expected_data_point) != type(  # noqa: E721
+            data_point
+        ) or not isinstance(
             expected_data_point, (HistogramDataPoint, NumberDataPoint)
         ):
             return False
diff --git a/tox.ini b/tox.ini
index 351054f26ed..e3f0866f523 100644
--- a/tox.ini
+++ b/tox.ini
@@ -191,7 +191,7 @@ commands =
   mypyinstalled: mypy --install-types --non-interactive --namespace-packages opentelemetry-api/tests/mypysmoke.py --strict
 
 [testenv:spellcheck]
-basepython: python3.10
+basepython: python3
 recreate = True
 deps =
   codespell
@@ -200,20 +200,10 @@ commands =
   codespell
 
 [testenv:lint]
-basepython: python3.10
+basepython: python3
 recreate = True
 deps =
-  -c dev-requirements.txt
-  asgiref
-  pylint
-  flake8
-  isort
-  black
-  psutil
-  readme_renderer
-  httpretty
-  GitPython
-  flaky
+  -r dev-requirements.txt
 
 commands_pre =
   python -m pip install -e {toxinidir}/opentelemetry-api[test]
@@ -245,20 +235,17 @@ commands =
   python scripts/eachdist.py lint --check-only
 
 [testenv:docs]
-# FIXME See #2984
-basepython: python3.9
+basepython: python3
 recreate = True
 deps =
   -c {toxinidir}/dev-requirements.txt
   -r {toxinidir}/docs-requirements.txt
-
 changedir = docs
-
 commands =
   sphinx-build -E -a -W -b html -T . _build/html
 
 [testenv:tracecontext]
-basepython: python3.10
+basepython: python3
 deps =
   # needed for tracecontext
   aiohttp~=3.6
@@ -284,11 +271,11 @@ commands =
 
 [testenv:docker-tests-proto{3,4}]
 deps =
-  pytest
+  pytest==7.1.3
   # Pinning PyYAML for issue: https://github.com/yaml/pyyaml/issues/724
-  PyYAML == 5.3.1
-  docker-compose >= 1.25.2
-  requests < 2.29.0
+  PyYAML==5.3.1
+  docker-compose==1.29.2
+  requests==2.28.2
 
   ; proto 3 and 4 tests install the respective version of protobuf
   proto3: protobuf~=3.19.0
@@ -320,9 +307,9 @@ commands_post =
   docker-compose down -v
 
 [testenv:public-symbols-check]
-basepython: python3.10
+basepython: python3
 recreate = True
 deps =
-  GitPython
+  GitPython==3.1.40
 commands =
   python {toxinidir}/scripts/public_symbols_checker.py