prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Replace 'backoff' dependency with a local implementation
  The 'backoff' dependency can be replaced with a few lines of code so I propose we remove it.
  
  **Is your feature request related to a problem?**
  There have been issues with the backoff dependency in the past, in particular relating to the transition from v1 to v2 and we have code and tests to deal with this transition.
  
  **Describe the solution you'd like**
  Replace the dependency with a function.
  
  **Describe alternatives you've considered**
  Keeping the status quo would also work, but the dependency appears to be more trouble than it's worth.
  
  **Additional context**
  PR [here](https://github.com/open-telemetry/opentelemetry-python/pull/3679)
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py`
  Content:
  ```
  1 # Copyright The OpenTelemetry Authors
  2 #
  3 # Licensed under the Apache License, Version 2.0 (the "License");
  4 # you may not use this file except in compliance with the License.
  5 # You may obtain a copy of the License at
  6 #
  7 #     http://www.apache.org/licenses/LICENSE-2.0
  8 #
  9 # Unless required by applicable law or agreed to in writing, software
  10 # distributed under the License is distributed on an "AS IS" BASIS,
  11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 # See the License for the specific language governing permissions and
  13 # limitations under the License.
  14 
  15 
  16 import logging
  17 from collections.abc import Sequence
  18 from typing import Any, Mapping, Optional, List, Callable, TypeVar, Dict
  19 
  20 import backoff
  21 
  22 from opentelemetry.sdk.util.instrumentation import InstrumentationScope
  23 from opentelemetry.proto.common.v1.common_pb2 import (
  24     InstrumentationScope as PB2InstrumentationScope,
  25 )
  26 from opentelemetry.proto.resource.v1.resource_pb2 import (
  27     Resource as PB2Resource,
  28 )
  29 from opentelemetry.proto.common.v1.common_pb2 import AnyValue as PB2AnyValue
  30 from opentelemetry.proto.common.v1.common_pb2 import KeyValue as PB2KeyValue
  31 from opentelemetry.proto.common.v1.common_pb2 import (
  32     KeyValueList as PB2KeyValueList,
  33 )
  34 from opentelemetry.proto.common.v1.common_pb2 import (
  35     ArrayValue as PB2ArrayValue,
  36 )
  37 from opentelemetry.sdk.trace import Resource
  38 from opentelemetry.util.types import Attributes
  39 
  40 
  41 _logger = logging.getLogger(__name__)
  42 
  43 _TypingResourceT = TypeVar("_TypingResourceT")
  44 _ResourceDataT = TypeVar("_ResourceDataT")
  45 
  46 
  47 def _encode_instrumentation_scope(
  48     instrumentation_scope: InstrumentationScope,
  49 ) -> PB2InstrumentationScope:
  50     if instrumentation_scope is None:
  51         return PB2InstrumentationScope()
  52     return PB2InstrumentationScope(
  53         name=instrumentation_scope.name,
  54         version=instrumentation_scope.version,
  55     )
  56 
  57 
  58 def _encode_resource(resource: Resource) -> PB2Resource:
  59     return PB2Resource(attributes=_encode_attributes(resource.attributes))
  60 
  61 
  62 def _encode_value(value: Any) -> PB2AnyValue:
  63     if isinstance(value, bool):
  64         return PB2AnyValue(bool_value=value)
  65     if isinstance(value, str):
  66         return PB2AnyValue(string_value=value)
  67     if isinstance(value, int):
  68         return PB2AnyValue(int_value=value)
  69     if isinstance(value, float):
  70         return PB2AnyValue(double_value=value)
  71     if isinstance(value, Sequence):
  72         return PB2AnyValue(
  73             array_value=PB2ArrayValue(values=[_encode_value(v) for v in value])
  74         )
  75     elif isinstance(value, Mapping):
  76         return PB2AnyValue(
  77             kvlist_value=PB2KeyValueList(
  78                 values=[_encode_key_value(str(k), v) for k, v in value.items()]
  79             )
  80         )
  81     raise Exception(f"Invalid type {type(value)} of value {value}")
  82 
  83 
  84 def _encode_key_value(key: str, value: Any) -> PB2KeyValue:
  85     return PB2KeyValue(key=key, value=_encode_value(value))
  86 
  87 
  88 def _encode_span_id(span_id: int) -> bytes:
  89     return span_id.to_bytes(length=8, byteorder="big", signed=False)
  90 
  91 
  92 def _encode_trace_id(trace_id: int) -> bytes:
  93     return trace_id.to_bytes(length=16, byteorder="big", signed=False)
  94 
  95 
  96 def _encode_attributes(
  97     attributes: Attributes,
  98 ) -> Optional[List[PB2KeyValue]]:
  99     if attributes:
  100         pb2_attributes = []
  101         for key, value in attributes.items():
  102             try:
  103                 pb2_attributes.append(_encode_key_value(key, value))
  104             except Exception as error:  # pylint: disable=broad-except
  105                 _logger.exception(error)
  106     else:
  107         pb2_attributes = None
  108     return pb2_attributes
  109 
  110 
  111 def _get_resource_data(
  112     sdk_resource_scope_data: Dict[Resource, _ResourceDataT],
  113     resource_class: Callable[..., _TypingResourceT],
  114     name: str,
  115 ) -> List[_TypingResourceT]:
  116 
  117     resource_data = []
  118 
  119     for (
  120         sdk_resource,
  121         scope_data,
  122     ) in sdk_resource_scope_data.items():
  123         collector_resource = PB2Resource(
  124             attributes=_encode_attributes(sdk_resource.attributes)
  125         )
  126         resource_data.append(
  127             resource_class(
  128                 **{
  129                     "resource": collector_resource,
  130                     "scope_{}".format(name): scope_data.values(),
  131                 }
  132             )
  133         )
  134     return resource_data
  135 
  136 
  137 # Work around API change between backoff 1.x and 2.x. Since 2.0.0 the backoff
  138 # wait generator API requires a first .send(None) before reading the backoff
  139 # values from the generator.
  140 _is_backoff_v2 = next(backoff.expo()) is None
  141 
  142 
  143 def _create_exp_backoff_generator(*args, **kwargs):
  144     gen = backoff.expo(*args, **kwargs)
  145     if _is_backoff_v2:
  146         gen.send(None)
  147     return gen
  148
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py b/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py
  --- a/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py
  +++ b/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py
  @@ -15,9 +15,17 @@
   
   import logging
   from collections.abc import Sequence
  -from typing import Any, Mapping, Optional, List, Callable, TypeVar, Dict
  -
  -import backoff
  +from itertools import count
  +from typing import (
  +    Any,
  +    Mapping,
  +    Optional,
  +    List,
  +    Callable,
  +    TypeVar,
  +    Dict,
  +    Iterator,
  +)
   
   from opentelemetry.sdk.util.instrumentation import InstrumentationScope
   from opentelemetry.proto.common.v1.common_pb2 import (
  @@ -37,7 +45,6 @@
   from opentelemetry.sdk.trace import Resource
   from opentelemetry.util.types import Attributes
   
  -
   _logger = logging.getLogger(__name__)
   
   _TypingResourceT = TypeVar("_TypingResourceT")
  @@ -113,7 +120,6 @@
       resource_class: Callable[..., _TypingResourceT],
       name: str,
   ) -> List[_TypingResourceT]:
  -
       resource_data = []
   
       for (
  @@ -134,14 +140,36 @@
       return resource_data
   
   
  -# Work around API change between backoff 1.x and 2.x. Since 2.0.0 the backoff
  -# wait generator API requires a first .send(None) before reading the backoff
  -# values from the generator.
  -_is_backoff_v2 = next(backoff.expo()) is None
  -
  -
  -def _create_exp_backoff_generator(*args, **kwargs):
  -    gen = backoff.expo(*args, **kwargs)
  -    if _is_backoff_v2:
  -        gen.send(None)
  -    return gen
  +def _create_exp_backoff_generator(max_value: int = 0) -> Iterator[int]:
  +    """
  +    Generates an infinite sequence of exponential backoff values. The sequence starts
  +    from 1 (2^0) and doubles each time (2^1, 2^2, 2^3, ...). If a max_value is specified
  +    and non-zero, the generated values will not exceed this maximum, capping at max_value
  +    instead of growing indefinitely.
  +
  +    Parameters:
  +    - max_value (int, optional): The maximum value to yield. If 0 or not provided, the
  +      sequence grows without bound.
  +
  +    Returns:
  +    Iterator[int]: An iterator that yields the exponential backoff values, either uncapped or
  +    capped at max_value.
  +
  +    Example:
  +    ```
  +    gen = _create_exp_backoff_generator(max_value=10)
  +    for _ in range(5):
  +        print(next(gen))
  +    ```
  +    This will print:
  +    1
  +    2
  +    4
  +    8
  +    10
  +
  +    Note: this functionality used to be handled by the 'backoff' package.
  +    """
  +    for i in count(0):
  +        out = 2**i
  +        yield min(out, max_value) if max_value else out
  
verification_info: {"golden_diff": "diff --git a/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py b/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py\n--- a/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py\n+++ b/exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py\n@@ -15,9 +15,17 @@\n \n import logging\n from collections.abc import Sequence\n-from typing import Any, Mapping, Optional, List, Callable, TypeVar, Dict\n-\n-import backoff\n+from itertools import count\n+from typing import (\n+    Any,\n+    Mapping,\n+    Optional,\n+    List,\n+    Callable,\n+    TypeVar,\n+    Dict,\n+    Iterator,\n+)\n \n from opentelemetry.sdk.util.instrumentation import InstrumentationScope\n from opentelemetry.proto.common.v1.common_pb2 import (\n@@ -37,7 +45,6 @@\n from opentelemetry.sdk.trace import Resource\n from opentelemetry.util.types import Attributes\n \n-\n _logger = logging.getLogger(__name__)\n \n _TypingResourceT = TypeVar(\"_TypingResourceT\")\n@@ -113,7 +120,6 @@\n     resource_class: Callable[..., _TypingResourceT],\n     name: str,\n ) -> List[_TypingResourceT]:\n-\n     resource_data = []\n \n     for (\n@@ -134,14 +140,36 @@\n     return resource_data\n \n \n-# Work around API change between backoff 1.x and 2.x. Since 2.0.0 the backoff\n-# wait generator API requires a first .send(None) before reading the backoff\n-# values from the generator.\n-_is_backoff_v2 = next(backoff.expo()) is None\n-\n-\n-def _create_exp_backoff_generator(*args, **kwargs):\n-    gen = backoff.expo(*args, **kwargs)\n-    if _is_backoff_v2:\n-        gen.send(None)\n-    return gen\n+def _create_exp_backoff_generator(max_value: int = 0) -> Iterator[int]:\n+    \"\"\"\n+    Generates an infinite sequence of exponential backoff values. The sequence starts\n+    from 1 (2^0) and doubles each time (2^1, 2^2, 2^3, ...). If a max_value is specified\n+    and non-zero, the generated values will not exceed this maximum, capping at max_value\n+    instead of growing indefinitely.\n+\n+    Parameters:\n+    - max_value (int, optional): The maximum value to yield. If 0 or not provided, the\n+      sequence grows without bound.\n+\n+    Returns:\n+    Iterator[int]: An iterator that yields the exponential backoff values, either uncapped or\n+    capped at max_value.\n+\n+    Example:\n+    ```\n+    gen = _create_exp_backoff_generator(max_value=10)\n+    for _ in range(5):\n+        print(next(gen))\n+    ```\n+    This will print:\n+    1\n+    2\n+    4\n+    8\n+    10\n+\n+    Note: this functionality used to be handled by the 'backoff' package.\n+    \"\"\"\n+    for i in count(0):\n+        out = 2**i\n+        yield min(out, max_value) if max_value else out\n", "issue": "Replace 'backoff' dependency with a local implementation\nThe 'backoff' dependency can be replaced with a few lines of code so I propose we remove it.\r\n\r\n**Is your feature request related to a problem?**\r\nThere have been issues with the backoff dependency in the past, in particular relating to the transition from v1 to v2 and we have code and tests to deal with this transition.\r\n\r\n**Describe the solution you'd like**\r\nReplace the dependency with a function.\r\n\r\n**Describe alternatives you've considered**\r\nKeeping the status quo would also work, but the dependency appears to be more trouble than it's worth.\r\n\r\n**Additional context**\r\nPR [here](https://github.com/open-telemetry/opentelemetry-python/pull/3679)\n", "before_files": [{"content": "# Copyright The OpenTelemetry Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\nimport logging\nfrom collections.abc import Sequence\nfrom typing import Any, Mapping, Optional, List, Callable, TypeVar, Dict\n\nimport backoff\n\nfrom opentelemetry.sdk.util.instrumentation import InstrumentationScope\nfrom opentelemetry.proto.common.v1.common_pb2 import (\n    InstrumentationScope as PB2InstrumentationScope,\n)\nfrom opentelemetry.proto.resource.v1.resource_pb2 import (\n    Resource as PB2Resource,\n)\nfrom opentelemetry.proto.common.v1.common_pb2 import AnyValue as PB2AnyValue\nfrom opentelemetry.proto.common.v1.common_pb2 import KeyValue as PB2KeyValue\nfrom opentelemetry.proto.common.v1.common_pb2 import (\n    KeyValueList as PB2KeyValueList,\n)\nfrom opentelemetry.proto.common.v1.common_pb2 import (\n    ArrayValue as PB2ArrayValue,\n)\nfrom opentelemetry.sdk.trace import Resource\nfrom opentelemetry.util.types import Attributes\n\n\n_logger = logging.getLogger(__name__)\n\n_TypingResourceT = TypeVar(\"_TypingResourceT\")\n_ResourceDataT = TypeVar(\"_ResourceDataT\")\n\n\ndef _encode_instrumentation_scope(\n    instrumentation_scope: InstrumentationScope,\n) -> PB2InstrumentationScope:\n    if instrumentation_scope is None:\n        return PB2InstrumentationScope()\n    return PB2InstrumentationScope(\n        name=instrumentation_scope.name,\n        version=instrumentation_scope.version,\n    )\n\n\ndef _encode_resource(resource: Resource) -> PB2Resource:\n    return PB2Resource(attributes=_encode_attributes(resource.attributes))\n\n\ndef _encode_value(value: Any) -> PB2AnyValue:\n    if isinstance(value, bool):\n        return PB2AnyValue(bool_value=value)\n    if isinstance(value, str):\n        return PB2AnyValue(string_value=value)\n    if isinstance(value, int):\n        return PB2AnyValue(int_value=value)\n    if isinstance(value, float):\n        return PB2AnyValue(double_value=value)\n    if isinstance(value, Sequence):\n        return PB2AnyValue(\n            array_value=PB2ArrayValue(values=[_encode_value(v) for v in value])\n        )\n    elif isinstance(value, Mapping):\n        return PB2AnyValue(\n            kvlist_value=PB2KeyValueList(\n                values=[_encode_key_value(str(k), v) for k, v in value.items()]\n            )\n        )\n    raise Exception(f\"Invalid type {type(value)} of value {value}\")\n\n\ndef _encode_key_value(key: str, value: Any) -> PB2KeyValue:\n    return PB2KeyValue(key=key, value=_encode_value(value))\n\n\ndef _encode_span_id(span_id: int) -> bytes:\n    return span_id.to_bytes(length=8, byteorder=\"big\", signed=False)\n\n\ndef _encode_trace_id(trace_id: int) -> bytes:\n    return trace_id.to_bytes(length=16, byteorder=\"big\", signed=False)\n\n\ndef _encode_attributes(\n    attributes: Attributes,\n) -> Optional[List[PB2KeyValue]]:\n    if attributes:\n        pb2_attributes = []\n        for key, value in attributes.items():\n            try:\n                pb2_attributes.append(_encode_key_value(key, value))\n            except Exception as error:  # pylint: disable=broad-except\n                _logger.exception(error)\n    else:\n        pb2_attributes = None\n    return pb2_attributes\n\n\ndef _get_resource_data(\n    sdk_resource_scope_data: Dict[Resource, _ResourceDataT],\n    resource_class: Callable[..., _TypingResourceT],\n    name: str,\n) -> List[_TypingResourceT]:\n\n    resource_data = []\n\n    for (\n        sdk_resource,\n        scope_data,\n    ) in sdk_resource_scope_data.items():\n        collector_resource = PB2Resource(\n            attributes=_encode_attributes(sdk_resource.attributes)\n        )\n        resource_data.append(\n            resource_class(\n                **{\n                    \"resource\": collector_resource,\n                    \"scope_{}\".format(name): scope_data.values(),\n                }\n            )\n        )\n    return resource_data\n\n\n# Work around API change between backoff 1.x and 2.x. Since 2.0.0 the backoff\n# wait generator API requires a first .send(None) before reading the backoff\n# values from the generator.\n_is_backoff_v2 = next(backoff.expo()) is None\n\n\ndef _create_exp_backoff_generator(*args, **kwargs):\n    gen = backoff.expo(*args, **kwargs)\n    if _is_backoff_v2:\n        gen.send(None)\n    return gen\n", "path": "exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py"}], "after_files": [{"content": "# Copyright The OpenTelemetry Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\nimport logging\nfrom collections.abc import Sequence\nfrom itertools import count\nfrom typing import (\n    Any,\n    Mapping,\n    Optional,\n    List,\n    Callable,\n    TypeVar,\n    Dict,\n    Iterator,\n)\n\nfrom opentelemetry.sdk.util.instrumentation import InstrumentationScope\nfrom opentelemetry.proto.common.v1.common_pb2 import (\n    InstrumentationScope as PB2InstrumentationScope,\n)\nfrom opentelemetry.proto.resource.v1.resource_pb2 import (\n    Resource as PB2Resource,\n)\nfrom opentelemetry.proto.common.v1.common_pb2 import AnyValue as PB2AnyValue\nfrom opentelemetry.proto.common.v1.common_pb2 import KeyValue as PB2KeyValue\nfrom opentelemetry.proto.common.v1.common_pb2 import (\n    KeyValueList as PB2KeyValueList,\n)\nfrom opentelemetry.proto.common.v1.common_pb2 import (\n    ArrayValue as PB2ArrayValue,\n)\nfrom opentelemetry.sdk.trace import Resource\nfrom opentelemetry.util.types import Attributes\n\n_logger = logging.getLogger(__name__)\n\n_TypingResourceT = TypeVar(\"_TypingResourceT\")\n_ResourceDataT = TypeVar(\"_ResourceDataT\")\n\n\ndef _encode_instrumentation_scope(\n    instrumentation_scope: InstrumentationScope,\n) -> PB2InstrumentationScope:\n    if instrumentation_scope is None:\n        return PB2InstrumentationScope()\n    return PB2InstrumentationScope(\n        name=instrumentation_scope.name,\n        version=instrumentation_scope.version,\n    )\n\n\ndef _encode_resource(resource: Resource) -> PB2Resource:\n    return PB2Resource(attributes=_encode_attributes(resource.attributes))\n\n\ndef _encode_value(value: Any) -> PB2AnyValue:\n    if isinstance(value, bool):\n        return PB2AnyValue(bool_value=value)\n    if isinstance(value, str):\n        return PB2AnyValue(string_value=value)\n    if isinstance(value, int):\n        return PB2AnyValue(int_value=value)\n    if isinstance(value, float):\n        return PB2AnyValue(double_value=value)\n    if isinstance(value, Sequence):\n        return PB2AnyValue(\n            array_value=PB2ArrayValue(values=[_encode_value(v) for v in value])\n        )\n    elif isinstance(value, Mapping):\n        return PB2AnyValue(\n            kvlist_value=PB2KeyValueList(\n                values=[_encode_key_value(str(k), v) for k, v in value.items()]\n            )\n        )\n    raise Exception(f\"Invalid type {type(value)} of value {value}\")\n\n\ndef _encode_key_value(key: str, value: Any) -> PB2KeyValue:\n    return PB2KeyValue(key=key, value=_encode_value(value))\n\n\ndef _encode_span_id(span_id: int) -> bytes:\n    return span_id.to_bytes(length=8, byteorder=\"big\", signed=False)\n\n\ndef _encode_trace_id(trace_id: int) -> bytes:\n    return trace_id.to_bytes(length=16, byteorder=\"big\", signed=False)\n\n\ndef _encode_attributes(\n    attributes: Attributes,\n) -> Optional[List[PB2KeyValue]]:\n    if attributes:\n        pb2_attributes = []\n        for key, value in attributes.items():\n            try:\n                pb2_attributes.append(_encode_key_value(key, value))\n            except Exception as error:  # pylint: disable=broad-except\n                _logger.exception(error)\n    else:\n        pb2_attributes = None\n    return pb2_attributes\n\n\ndef _get_resource_data(\n    sdk_resource_scope_data: Dict[Resource, _ResourceDataT],\n    resource_class: Callable[..., _TypingResourceT],\n    name: str,\n) -> List[_TypingResourceT]:\n    resource_data = []\n\n    for (\n        sdk_resource,\n        scope_data,\n    ) in sdk_resource_scope_data.items():\n        collector_resource = PB2Resource(\n            attributes=_encode_attributes(sdk_resource.attributes)\n        )\n        resource_data.append(\n            resource_class(\n                **{\n                    \"resource\": collector_resource,\n                    \"scope_{}\".format(name): scope_data.values(),\n                }\n            )\n        )\n    return resource_data\n\n\ndef _create_exp_backoff_generator(max_value: int = 0) -> Iterator[int]:\n    \"\"\"\n    Generates an infinite sequence of exponential backoff values. The sequence starts\n    from 1 (2^0) and doubles each time (2^1, 2^2, 2^3, ...). If a max_value is specified\n    and non-zero, the generated values will not exceed this maximum, capping at max_value\n    instead of growing indefinitely.\n\n    Parameters:\n    - max_value (int, optional): The maximum value to yield. If 0 or not provided, the\n      sequence grows without bound.\n\n    Returns:\n    Iterator[int]: An iterator that yields the exponential backoff values, either uncapped or\n    capped at max_value.\n\n    Example:\n    ```\n    gen = _create_exp_backoff_generator(max_value=10)\n    for _ in range(5):\n        print(next(gen))\n    ```\n    This will print:\n    1\n    2\n    4\n    8\n    10\n\n    Note: this functionality used to be handled by the 'backoff' package.\n    \"\"\"\n    for i in count(0):\n        out = 2**i\n        yield min(out, max_value) if max_value else out\n", "path": "exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py"}]}