prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Bug in b3 propagation
  When configuring b3 propagation, if the parent of a Span is an instance of a SpanContext, the following error occurs:
  
  `'SpanContext' object has no attribute 'context'`
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `opentelemetry-sdk/src/opentelemetry/sdk/trace/propagation/b3_format.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 import typing
  16 
  17 import opentelemetry.trace as trace
  18 from opentelemetry.context import Context
  19 from opentelemetry.trace.propagation import (
  20     get_span_from_context,
  21     set_span_in_context,
  22 )
  23 from opentelemetry.trace.propagation.httptextformat import (
  24     Getter,
  25     HTTPTextFormat,
  26     HTTPTextFormatT,
  27     Setter,
  28 )
  29 
  30 
  31 class B3Format(HTTPTextFormat):
  32     """Propagator for the B3 HTTP header format.
  33 
  34     See: https://github.com/openzipkin/b3-propagation
  35     """
  36 
  37     SINGLE_HEADER_KEY = "b3"
  38     TRACE_ID_KEY = "x-b3-traceid"
  39     SPAN_ID_KEY = "x-b3-spanid"
  40     PARENT_SPAN_ID_KEY = "x-b3-parentspanid"
  41     SAMPLED_KEY = "x-b3-sampled"
  42     FLAGS_KEY = "x-b3-flags"
  43     _SAMPLE_PROPAGATE_VALUES = set(["1", "True", "true", "d"])
  44 
  45     def extract(
  46         self,
  47         get_from_carrier: Getter[HTTPTextFormatT],
  48         carrier: HTTPTextFormatT,
  49         context: typing.Optional[Context] = None,
  50     ) -> Context:
  51         trace_id = format_trace_id(trace.INVALID_TRACE_ID)
  52         span_id = format_span_id(trace.INVALID_SPAN_ID)
  53         sampled = "0"
  54         flags = None
  55 
  56         single_header = _extract_first_element(
  57             get_from_carrier(carrier, self.SINGLE_HEADER_KEY)
  58         )
  59         if single_header:
  60             # The b3 spec calls for the sampling state to be
  61             # "deferred", which is unspecified. This concept does not
  62             # translate to SpanContext, so we set it as recorded.
  63             sampled = "1"
  64             fields = single_header.split("-", 4)
  65 
  66             if len(fields) == 1:
  67                 sampled = fields[0]
  68             elif len(fields) == 2:
  69                 trace_id, span_id = fields
  70             elif len(fields) == 3:
  71                 trace_id, span_id, sampled = fields
  72             elif len(fields) == 4:
  73                 trace_id, span_id, sampled, _ = fields
  74             else:
  75                 return set_span_in_context(trace.INVALID_SPAN)
  76         else:
  77             trace_id = (
  78                 _extract_first_element(
  79                     get_from_carrier(carrier, self.TRACE_ID_KEY)
  80                 )
  81                 or trace_id
  82             )
  83             span_id = (
  84                 _extract_first_element(
  85                     get_from_carrier(carrier, self.SPAN_ID_KEY)
  86                 )
  87                 or span_id
  88             )
  89             sampled = (
  90                 _extract_first_element(
  91                     get_from_carrier(carrier, self.SAMPLED_KEY)
  92                 )
  93                 or sampled
  94             )
  95             flags = (
  96                 _extract_first_element(
  97                     get_from_carrier(carrier, self.FLAGS_KEY)
  98                 )
  99                 or flags
  100             )
  101 
  102         options = 0
  103         # The b3 spec provides no defined behavior for both sample and
  104         # flag values set. Since the setting of at least one implies
  105         # the desire for some form of sampling, propagate if either
  106         # header is set to allow.
  107         if sampled in self._SAMPLE_PROPAGATE_VALUES or flags == "1":
  108             options |= trace.TraceFlags.SAMPLED
  109         return set_span_in_context(
  110             trace.DefaultSpan(
  111                 trace.SpanContext(
  112                     # trace an span ids are encoded in hex, so must be converted
  113                     trace_id=int(trace_id, 16),
  114                     span_id=int(span_id, 16),
  115                     is_remote=True,
  116                     trace_flags=trace.TraceFlags(options),
  117                     trace_state=trace.TraceState(),
  118                 )
  119             )
  120         )
  121 
  122     def inject(
  123         self,
  124         set_in_carrier: Setter[HTTPTextFormatT],
  125         carrier: HTTPTextFormatT,
  126         context: typing.Optional[Context] = None,
  127     ) -> None:
  128         span = get_span_from_context(context=context)
  129         sampled = (trace.TraceFlags.SAMPLED & span.context.trace_flags) != 0
  130         set_in_carrier(
  131             carrier, self.TRACE_ID_KEY, format_trace_id(span.context.trace_id),
  132         )
  133         set_in_carrier(
  134             carrier, self.SPAN_ID_KEY, format_span_id(span.context.span_id)
  135         )
  136         if span.parent is not None:
  137             set_in_carrier(
  138                 carrier,
  139                 self.PARENT_SPAN_ID_KEY,
  140                 format_span_id(span.parent.context.span_id),
  141             )
  142         set_in_carrier(carrier, self.SAMPLED_KEY, "1" if sampled else "0")
  143 
  144 
  145 def format_trace_id(trace_id: int) -> str:
  146     """Format the trace id according to b3 specification."""
  147     return format(trace_id, "032x")
  148 
  149 
  150 def format_span_id(span_id: int) -> str:
  151     """Format the span id according to b3 specification."""
  152     return format(span_id, "016x")
  153 
  154 
  155 def _extract_first_element(
  156     items: typing.Iterable[HTTPTextFormatT],
  157 ) -> typing.Optional[HTTPTextFormatT]:
  158     if items is None:
  159         return None
  160     return next(iter(items), None)
  161
  ```
  --- 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/opentelemetry-sdk/src/opentelemetry/sdk/trace/propagation/b3_format.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/propagation/b3_format.py
  --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/propagation/b3_format.py
  +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/propagation/b3_format.py
  @@ -137,7 +137,7 @@
               set_in_carrier(
                   carrier,
                   self.PARENT_SPAN_ID_KEY,
  -                format_span_id(span.parent.context.span_id),
  +                format_span_id(span.parent.span_id),
               )
           set_in_carrier(carrier, self.SAMPLED_KEY, "1" if sampled else "0")
  
verification_info: {"golden_diff": "diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/propagation/b3_format.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/propagation/b3_format.py\n--- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/propagation/b3_format.py\n+++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/propagation/b3_format.py\n@@ -137,7 +137,7 @@\n             set_in_carrier(\n                 carrier,\n                 self.PARENT_SPAN_ID_KEY,\n-                format_span_id(span.parent.context.span_id),\n+                format_span_id(span.parent.span_id),\n             )\n         set_in_carrier(carrier, self.SAMPLED_KEY, \"1\" if sampled else \"0\")\n", "issue": "Bug in b3 propagation\nWhen configuring b3 propagation, if the parent of a Span is an instance of a SpanContext, the following error occurs:\r\n\r\n`'SpanContext' object has no attribute 'context'`\r\n\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\nimport typing\n\nimport opentelemetry.trace as trace\nfrom opentelemetry.context import Context\nfrom opentelemetry.trace.propagation import (\n    get_span_from_context,\n    set_span_in_context,\n)\nfrom opentelemetry.trace.propagation.httptextformat import (\n    Getter,\n    HTTPTextFormat,\n    HTTPTextFormatT,\n    Setter,\n)\n\n\nclass B3Format(HTTPTextFormat):\n    \"\"\"Propagator for the B3 HTTP header format.\n\n    See: https://github.com/openzipkin/b3-propagation\n    \"\"\"\n\n    SINGLE_HEADER_KEY = \"b3\"\n    TRACE_ID_KEY = \"x-b3-traceid\"\n    SPAN_ID_KEY = \"x-b3-spanid\"\n    PARENT_SPAN_ID_KEY = \"x-b3-parentspanid\"\n    SAMPLED_KEY = \"x-b3-sampled\"\n    FLAGS_KEY = \"x-b3-flags\"\n    _SAMPLE_PROPAGATE_VALUES = set([\"1\", \"True\", \"true\", \"d\"])\n\n    def extract(\n        self,\n        get_from_carrier: Getter[HTTPTextFormatT],\n        carrier: HTTPTextFormatT,\n        context: typing.Optional[Context] = None,\n    ) -> Context:\n        trace_id = format_trace_id(trace.INVALID_TRACE_ID)\n        span_id = format_span_id(trace.INVALID_SPAN_ID)\n        sampled = \"0\"\n        flags = None\n\n        single_header = _extract_first_element(\n            get_from_carrier(carrier, self.SINGLE_HEADER_KEY)\n        )\n        if single_header:\n            # The b3 spec calls for the sampling state to be\n            # \"deferred\", which is unspecified. This concept does not\n            # translate to SpanContext, so we set it as recorded.\n            sampled = \"1\"\n            fields = single_header.split(\"-\", 4)\n\n            if len(fields) == 1:\n                sampled = fields[0]\n            elif len(fields) == 2:\n                trace_id, span_id = fields\n            elif len(fields) == 3:\n                trace_id, span_id, sampled = fields\n            elif len(fields) == 4:\n                trace_id, span_id, sampled, _ = fields\n            else:\n                return set_span_in_context(trace.INVALID_SPAN)\n        else:\n            trace_id = (\n                _extract_first_element(\n                    get_from_carrier(carrier, self.TRACE_ID_KEY)\n                )\n                or trace_id\n            )\n            span_id = (\n                _extract_first_element(\n                    get_from_carrier(carrier, self.SPAN_ID_KEY)\n                )\n                or span_id\n            )\n            sampled = (\n                _extract_first_element(\n                    get_from_carrier(carrier, self.SAMPLED_KEY)\n                )\n                or sampled\n            )\n            flags = (\n                _extract_first_element(\n                    get_from_carrier(carrier, self.FLAGS_KEY)\n                )\n                or flags\n            )\n\n        options = 0\n        # The b3 spec provides no defined behavior for both sample and\n        # flag values set. Since the setting of at least one implies\n        # the desire for some form of sampling, propagate if either\n        # header is set to allow.\n        if sampled in self._SAMPLE_PROPAGATE_VALUES or flags == \"1\":\n            options |= trace.TraceFlags.SAMPLED\n        return set_span_in_context(\n            trace.DefaultSpan(\n                trace.SpanContext(\n                    # trace an span ids are encoded in hex, so must be converted\n                    trace_id=int(trace_id, 16),\n                    span_id=int(span_id, 16),\n                    is_remote=True,\n                    trace_flags=trace.TraceFlags(options),\n                    trace_state=trace.TraceState(),\n                )\n            )\n        )\n\n    def inject(\n        self,\n        set_in_carrier: Setter[HTTPTextFormatT],\n        carrier: HTTPTextFormatT,\n        context: typing.Optional[Context] = None,\n    ) -> None:\n        span = get_span_from_context(context=context)\n        sampled = (trace.TraceFlags.SAMPLED & span.context.trace_flags) != 0\n        set_in_carrier(\n            carrier, self.TRACE_ID_KEY, format_trace_id(span.context.trace_id),\n        )\n        set_in_carrier(\n            carrier, self.SPAN_ID_KEY, format_span_id(span.context.span_id)\n        )\n        if span.parent is not None:\n            set_in_carrier(\n                carrier,\n                self.PARENT_SPAN_ID_KEY,\n                format_span_id(span.parent.context.span_id),\n            )\n        set_in_carrier(carrier, self.SAMPLED_KEY, \"1\" if sampled else \"0\")\n\n\ndef format_trace_id(trace_id: int) -> str:\n    \"\"\"Format the trace id according to b3 specification.\"\"\"\n    return format(trace_id, \"032x\")\n\n\ndef format_span_id(span_id: int) -> str:\n    \"\"\"Format the span id according to b3 specification.\"\"\"\n    return format(span_id, \"016x\")\n\n\ndef _extract_first_element(\n    items: typing.Iterable[HTTPTextFormatT],\n) -> typing.Optional[HTTPTextFormatT]:\n    if items is None:\n        return None\n    return next(iter(items), None)\n", "path": "opentelemetry-sdk/src/opentelemetry/sdk/trace/propagation/b3_format.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\nimport typing\n\nimport opentelemetry.trace as trace\nfrom opentelemetry.context import Context\nfrom opentelemetry.trace.propagation import (\n    get_span_from_context,\n    set_span_in_context,\n)\nfrom opentelemetry.trace.propagation.httptextformat import (\n    Getter,\n    HTTPTextFormat,\n    HTTPTextFormatT,\n    Setter,\n)\n\n\nclass B3Format(HTTPTextFormat):\n    \"\"\"Propagator for the B3 HTTP header format.\n\n    See: https://github.com/openzipkin/b3-propagation\n    \"\"\"\n\n    SINGLE_HEADER_KEY = \"b3\"\n    TRACE_ID_KEY = \"x-b3-traceid\"\n    SPAN_ID_KEY = \"x-b3-spanid\"\n    PARENT_SPAN_ID_KEY = \"x-b3-parentspanid\"\n    SAMPLED_KEY = \"x-b3-sampled\"\n    FLAGS_KEY = \"x-b3-flags\"\n    _SAMPLE_PROPAGATE_VALUES = set([\"1\", \"True\", \"true\", \"d\"])\n\n    def extract(\n        self,\n        get_from_carrier: Getter[HTTPTextFormatT],\n        carrier: HTTPTextFormatT,\n        context: typing.Optional[Context] = None,\n    ) -> Context:\n        trace_id = format_trace_id(trace.INVALID_TRACE_ID)\n        span_id = format_span_id(trace.INVALID_SPAN_ID)\n        sampled = \"0\"\n        flags = None\n\n        single_header = _extract_first_element(\n            get_from_carrier(carrier, self.SINGLE_HEADER_KEY)\n        )\n        if single_header:\n            # The b3 spec calls for the sampling state to be\n            # \"deferred\", which is unspecified. This concept does not\n            # translate to SpanContext, so we set it as recorded.\n            sampled = \"1\"\n            fields = single_header.split(\"-\", 4)\n\n            if len(fields) == 1:\n                sampled = fields[0]\n            elif len(fields) == 2:\n                trace_id, span_id = fields\n            elif len(fields) == 3:\n                trace_id, span_id, sampled = fields\n            elif len(fields) == 4:\n                trace_id, span_id, sampled, _ = fields\n            else:\n                return set_span_in_context(trace.INVALID_SPAN)\n        else:\n            trace_id = (\n                _extract_first_element(\n                    get_from_carrier(carrier, self.TRACE_ID_KEY)\n                )\n                or trace_id\n            )\n            span_id = (\n                _extract_first_element(\n                    get_from_carrier(carrier, self.SPAN_ID_KEY)\n                )\n                or span_id\n            )\n            sampled = (\n                _extract_first_element(\n                    get_from_carrier(carrier, self.SAMPLED_KEY)\n                )\n                or sampled\n            )\n            flags = (\n                _extract_first_element(\n                    get_from_carrier(carrier, self.FLAGS_KEY)\n                )\n                or flags\n            )\n\n        options = 0\n        # The b3 spec provides no defined behavior for both sample and\n        # flag values set. Since the setting of at least one implies\n        # the desire for some form of sampling, propagate if either\n        # header is set to allow.\n        if sampled in self._SAMPLE_PROPAGATE_VALUES or flags == \"1\":\n            options |= trace.TraceFlags.SAMPLED\n        return set_span_in_context(\n            trace.DefaultSpan(\n                trace.SpanContext(\n                    # trace an span ids are encoded in hex, so must be converted\n                    trace_id=int(trace_id, 16),\n                    span_id=int(span_id, 16),\n                    is_remote=True,\n                    trace_flags=trace.TraceFlags(options),\n                    trace_state=trace.TraceState(),\n                )\n            )\n        )\n\n    def inject(\n        self,\n        set_in_carrier: Setter[HTTPTextFormatT],\n        carrier: HTTPTextFormatT,\n        context: typing.Optional[Context] = None,\n    ) -> None:\n        span = get_span_from_context(context=context)\n        sampled = (trace.TraceFlags.SAMPLED & span.context.trace_flags) != 0\n        set_in_carrier(\n            carrier, self.TRACE_ID_KEY, format_trace_id(span.context.trace_id),\n        )\n        set_in_carrier(\n            carrier, self.SPAN_ID_KEY, format_span_id(span.context.span_id)\n        )\n        if span.parent is not None:\n            set_in_carrier(\n                carrier,\n                self.PARENT_SPAN_ID_KEY,\n                format_span_id(span.parent.span_id),\n            )\n        set_in_carrier(carrier, self.SAMPLED_KEY, \"1\" if sampled else \"0\")\n\n\ndef format_trace_id(trace_id: int) -> str:\n    \"\"\"Format the trace id according to b3 specification.\"\"\"\n    return format(trace_id, \"032x\")\n\n\ndef format_span_id(span_id: int) -> str:\n    \"\"\"Format the span id according to b3 specification.\"\"\"\n    return format(span_id, \"016x\")\n\n\ndef _extract_first_element(\n    items: typing.Iterable[HTTPTextFormatT],\n) -> typing.Optional[HTTPTextFormatT]:\n    if items is None:\n        return None\n    return next(iter(items), None)\n", "path": "opentelemetry-sdk/src/opentelemetry/sdk/trace/propagation/b3_format.py"}]}