We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Otel Spec forbids B3 propagator from propagating `X-B3-ParentSpanId`
From the [spec](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/api-propagators.md#b3-inject)

> MUST NOT propagate X-B3-ParentSpanId as OpenTelemetry does not support reusing the same id for both sides of a request.

But we do it [here](https://github.com/open-telemetry/opentelemetry-python/blob/61c2d6e1508c75cce4b50ff7b28712c944b94128/propagator/opentelemetry-propagator-b3/src/opentelemetry/propagators/b3/__init__.py#L152-L158)

This should be removed as the spec forbids it. 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `propagator/opentelemetry-propagator-b3/src/opentelemetry/propagators/b3/__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 import typing
16 from re import compile as re_compile
17 
18 from deprecated import deprecated
19 
20 from opentelemetry import trace
21 from opentelemetry.context import Context
22 from opentelemetry.propagators.textmap import (
23     CarrierT,
24     Getter,
25     Setter,
26     TextMapPropagator,
27     default_getter,
28     default_setter,
29 )
30 from opentelemetry.trace import format_span_id, format_trace_id
31 
32 
33 class B3MultiFormat(TextMapPropagator):
34     """Propagator for the B3 HTTP multi-header format.
35 
36     See: https://github.com/openzipkin/b3-propagation
37          https://github.com/openzipkin/b3-propagation#multiple-headers
38     """
39 
40     SINGLE_HEADER_KEY = "b3"
41     TRACE_ID_KEY = "x-b3-traceid"
42     SPAN_ID_KEY = "x-b3-spanid"
43     PARENT_SPAN_ID_KEY = "x-b3-parentspanid"
44     SAMPLED_KEY = "x-b3-sampled"
45     FLAGS_KEY = "x-b3-flags"
46     _SAMPLE_PROPAGATE_VALUES = set(["1", "True", "true", "d"])
47     _trace_id_regex = re_compile(r"[\da-fA-F]{16}|[\da-fA-F]{32}")
48     _span_id_regex = re_compile(r"[\da-fA-F]{16}")
49 
50     def extract(
51         self,
52         carrier: CarrierT,
53         context: typing.Optional[Context] = None,
54         getter: Getter = default_getter,
55     ) -> Context:
56         if context is None:
57             context = Context()
58         trace_id = trace.INVALID_TRACE_ID
59         span_id = trace.INVALID_SPAN_ID
60         sampled = "0"
61         flags = None
62 
63         single_header = _extract_first_element(
64             getter.get(carrier, self.SINGLE_HEADER_KEY)
65         )
66         if single_header:
67             # The b3 spec calls for the sampling state to be
68             # "deferred", which is unspecified. This concept does not
69             # translate to SpanContext, so we set it as recorded.
70             sampled = "1"
71             fields = single_header.split("-", 4)
72 
73             if len(fields) == 1:
74                 sampled = fields[0]
75             elif len(fields) == 2:
76                 trace_id, span_id = fields
77             elif len(fields) == 3:
78                 trace_id, span_id, sampled = fields
79             elif len(fields) == 4:
80                 trace_id, span_id, sampled, _ = fields
81         else:
82             trace_id = (
83                 _extract_first_element(getter.get(carrier, self.TRACE_ID_KEY))
84                 or trace_id
85             )
86             span_id = (
87                 _extract_first_element(getter.get(carrier, self.SPAN_ID_KEY))
88                 or span_id
89             )
90             sampled = (
91                 _extract_first_element(getter.get(carrier, self.SAMPLED_KEY))
92                 or sampled
93             )
94             flags = (
95                 _extract_first_element(getter.get(carrier, self.FLAGS_KEY))
96                 or flags
97             )
98 
99         if (
100             trace_id == trace.INVALID_TRACE_ID
101             or span_id == trace.INVALID_SPAN_ID
102             or self._trace_id_regex.fullmatch(trace_id) is None
103             or self._span_id_regex.fullmatch(span_id) is None
104         ):
105             return context
106 
107         trace_id = int(trace_id, 16)
108         span_id = int(span_id, 16)
109         options = 0
110         # The b3 spec provides no defined behavior for both sample and
111         # flag values set. Since the setting of at least one implies
112         # the desire for some form of sampling, propagate if either
113         # header is set to allow.
114         if sampled in self._SAMPLE_PROPAGATE_VALUES or flags == "1":
115             options |= trace.TraceFlags.SAMPLED
116 
117         return trace.set_span_in_context(
118             trace.NonRecordingSpan(
119                 trace.SpanContext(
120                     # trace an span ids are encoded in hex, so must be converted
121                     trace_id=trace_id,
122                     span_id=span_id,
123                     is_remote=True,
124                     trace_flags=trace.TraceFlags(options),
125                     trace_state=trace.TraceState(),
126                 )
127             ),
128             context,
129         )
130 
131     def inject(
132         self,
133         carrier: CarrierT,
134         context: typing.Optional[Context] = None,
135         setter: Setter = default_setter,
136     ) -> None:
137         span = trace.get_current_span(context=context)
138 
139         span_context = span.get_span_context()
140         if span_context == trace.INVALID_SPAN_CONTEXT:
141             return
142 
143         sampled = (trace.TraceFlags.SAMPLED & span_context.trace_flags) != 0
144         setter.set(
145             carrier,
146             self.TRACE_ID_KEY,
147             format_trace_id(span_context.trace_id),
148         )
149         setter.set(
150             carrier, self.SPAN_ID_KEY, format_span_id(span_context.span_id)
151         )
152         span_parent = getattr(span, "parent", None)
153         if span_parent is not None:
154             setter.set(
155                 carrier,
156                 self.PARENT_SPAN_ID_KEY,
157                 format_span_id(span_parent.span_id),
158             )
159         setter.set(carrier, self.SAMPLED_KEY, "1" if sampled else "0")
160 
161     @property
162     def fields(self) -> typing.Set[str]:
163         return {
164             self.TRACE_ID_KEY,
165             self.SPAN_ID_KEY,
166             self.PARENT_SPAN_ID_KEY,
167             self.SAMPLED_KEY,
168         }
169 
170 
171 class B3SingleFormat(B3MultiFormat):
172     """Propagator for the B3 HTTP single-header format.
173 
174     See: https://github.com/openzipkin/b3-propagation
175          https://github.com/openzipkin/b3-propagation#single-header
176     """
177 
178     def inject(
179         self,
180         carrier: CarrierT,
181         context: typing.Optional[Context] = None,
182         setter: Setter = default_setter,
183     ) -> None:
184         span = trace.get_current_span(context=context)
185 
186         span_context = span.get_span_context()
187         if span_context == trace.INVALID_SPAN_CONTEXT:
188             return
189 
190         sampled = (trace.TraceFlags.SAMPLED & span_context.trace_flags) != 0
191 
192         fields = [
193             format_trace_id(span_context.trace_id),
194             format_span_id(span_context.span_id),
195             "1" if sampled else "0",
196         ]
197 
198         span_parent = getattr(span, "parent", None)
199         if span_parent:
200             fields.append(format_span_id(span_parent.span_id))
201 
202         setter.set(carrier, self.SINGLE_HEADER_KEY, "-".join(fields))
203 
204     @property
205     def fields(self) -> typing.Set[str]:
206         return {self.SINGLE_HEADER_KEY}
207 
208 
209 class B3Format(B3MultiFormat):
210     @deprecated(
211         version="1.2.0",
212         reason="B3Format is deprecated in favor of B3MultiFormat",
213     )
214     def __init__(self, *args, **kwargs):
215         super().__init__(*args, **kwargs)
216 
217 
218 def _extract_first_element(
219     items: typing.Iterable[CarrierT],
220 ) -> typing.Optional[CarrierT]:
221     if items is None:
222         return None
223     return next(iter(items), None)
224
```
--- 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()

```

diff --git a/propagator/opentelemetry-propagator-b3/src/opentelemetry/propagators/b3/__init__.py b/propagator/opentelemetry-propagator-b3/src/opentelemetry/propagators/b3/__init__.py
--- a/propagator/opentelemetry-propagator-b3/src/opentelemetry/propagators/b3/__init__.py
+++ b/propagator/opentelemetry-propagator-b3/src/opentelemetry/propagators/b3/__init__.py
@@ -40,7 +40,6 @@
     SINGLE_HEADER_KEY = "b3"
     TRACE_ID_KEY = "x-b3-traceid"
     SPAN_ID_KEY = "x-b3-spanid"
-    PARENT_SPAN_ID_KEY = "x-b3-parentspanid"
     SAMPLED_KEY = "x-b3-sampled"
     FLAGS_KEY = "x-b3-flags"
     _SAMPLE_PROPAGATE_VALUES = set(["1", "True", "true", "d"])
@@ -149,13 +148,6 @@
         setter.set(
             carrier, self.SPAN_ID_KEY, format_span_id(span_context.span_id)
         )
-        span_parent = getattr(span, "parent", None)
-        if span_parent is not None:
-            setter.set(
-                carrier,
-                self.PARENT_SPAN_ID_KEY,
-                format_span_id(span_parent.span_id),
-            )
         setter.set(carrier, self.SAMPLED_KEY, "1" if sampled else "0")
 
     @property
@@ -163,7 +155,6 @@
         return {
             self.TRACE_ID_KEY,
             self.SPAN_ID_KEY,
-            self.PARENT_SPAN_ID_KEY,
             self.SAMPLED_KEY,
         }
 
@@ -195,10 +186,6 @@
             "1" if sampled else "0",
         ]
 
-        span_parent = getattr(span, "parent", None)
-        if span_parent:
-            fields.append(format_span_id(span_parent.span_id))
-
         setter.set(carrier, self.SINGLE_HEADER_KEY, "-".join(fields))
 
     @property

{"golden_diff": "diff --git a/propagator/opentelemetry-propagator-b3/src/opentelemetry/propagators/b3/__init__.py b/propagator/opentelemetry-propagator-b3/src/opentelemetry/propagators/b3/__init__.py\n--- a/propagator/opentelemetry-propagator-b3/src/opentelemetry/propagators/b3/__init__.py\n+++ b/propagator/opentelemetry-propagator-b3/src/opentelemetry/propagators/b3/__init__.py\n@@ -40,7 +40,6 @@\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@@ -149,13 +148,6 @@\n         setter.set(\n             carrier, self.SPAN_ID_KEY, format_span_id(span_context.span_id)\n         )\n-        span_parent = getattr(span, \"parent\", None)\n-        if span_parent is not None:\n-            setter.set(\n-                carrier,\n-                self.PARENT_SPAN_ID_KEY,\n-                format_span_id(span_parent.span_id),\n-            )\n         setter.set(carrier, self.SAMPLED_KEY, \"1\" if sampled else \"0\")\n \n     @property\n@@ -163,7 +155,6 @@\n         return {\n             self.TRACE_ID_KEY,\n             self.SPAN_ID_KEY,\n-            self.PARENT_SPAN_ID_KEY,\n             self.SAMPLED_KEY,\n         }\n \n@@ -195,10 +186,6 @@\n             \"1\" if sampled else \"0\",\n         ]\n \n-        span_parent = getattr(span, \"parent\", None)\n-        if span_parent:\n-            fields.append(format_span_id(span_parent.span_id))\n-\n         setter.set(carrier, self.SINGLE_HEADER_KEY, \"-\".join(fields))\n \n     @property\n", "issue": "Otel Spec forbids B3 propagator from propagating `X-B3-ParentSpanId`\nFrom the [spec](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/api-propagators.md#b3-inject)\r\n\r\n> MUST NOT propagate X-B3-ParentSpanId as OpenTelemetry does not support reusing the same id for both sides of a request.\r\n\r\nBut we do it [here](https://github.com/open-telemetry/opentelemetry-python/blob/61c2d6e1508c75cce4b50ff7b28712c944b94128/propagator/opentelemetry-propagator-b3/src/opentelemetry/propagators/b3/__init__.py#L152-L158)\r\n\r\nThis should be removed as the spec forbids it. \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\nfrom re import compile as re_compile\n\nfrom deprecated import deprecated\n\nfrom opentelemetry import trace\nfrom opentelemetry.context import Context\nfrom opentelemetry.propagators.textmap import (\n    CarrierT,\n    Getter,\n    Setter,\n    TextMapPropagator,\n    default_getter,\n    default_setter,\n)\nfrom opentelemetry.trace import format_span_id, format_trace_id\n\n\nclass B3MultiFormat(TextMapPropagator):\n    \"\"\"Propagator for the B3 HTTP multi-header format.\n\n    See: https://github.com/openzipkin/b3-propagation\n         https://github.com/openzipkin/b3-propagation#multiple-headers\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    _trace_id_regex = re_compile(r\"[\\da-fA-F]{16}|[\\da-fA-F]{32}\")\n    _span_id_regex = re_compile(r\"[\\da-fA-F]{16}\")\n\n    def extract(\n        self,\n        carrier: CarrierT,\n        context: typing.Optional[Context] = None,\n        getter: Getter = default_getter,\n    ) -> Context:\n        if context is None:\n            context = Context()\n        trace_id = trace.INVALID_TRACE_ID\n        span_id = trace.INVALID_SPAN_ID\n        sampled = \"0\"\n        flags = None\n\n        single_header = _extract_first_element(\n            getter.get(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            trace_id = (\n                _extract_first_element(getter.get(carrier, self.TRACE_ID_KEY))\n                or trace_id\n            )\n            span_id = (\n                _extract_first_element(getter.get(carrier, self.SPAN_ID_KEY))\n                or span_id\n            )\n            sampled = (\n                _extract_first_element(getter.get(carrier, self.SAMPLED_KEY))\n                or sampled\n            )\n            flags = (\n                _extract_first_element(getter.get(carrier, self.FLAGS_KEY))\n                or flags\n            )\n\n        if (\n            trace_id == trace.INVALID_TRACE_ID\n            or span_id == trace.INVALID_SPAN_ID\n            or self._trace_id_regex.fullmatch(trace_id) is None\n            or self._span_id_regex.fullmatch(span_id) is None\n        ):\n            return context\n\n        trace_id = int(trace_id, 16)\n        span_id = int(span_id, 16)\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\n        return trace.set_span_in_context(\n            trace.NonRecordingSpan(\n                trace.SpanContext(\n                    # trace an span ids are encoded in hex, so must be converted\n                    trace_id=trace_id,\n                    span_id=span_id,\n                    is_remote=True,\n                    trace_flags=trace.TraceFlags(options),\n                    trace_state=trace.TraceState(),\n                )\n            ),\n            context,\n        )\n\n    def inject(\n        self,\n        carrier: CarrierT,\n        context: typing.Optional[Context] = None,\n        setter: Setter = default_setter,\n    ) -> None:\n        span = trace.get_current_span(context=context)\n\n        span_context = span.get_span_context()\n        if span_context == trace.INVALID_SPAN_CONTEXT:\n            return\n\n        sampled = (trace.TraceFlags.SAMPLED & span_context.trace_flags) != 0\n        setter.set(\n            carrier,\n            self.TRACE_ID_KEY,\n            format_trace_id(span_context.trace_id),\n        )\n        setter.set(\n            carrier, self.SPAN_ID_KEY, format_span_id(span_context.span_id)\n        )\n        span_parent = getattr(span, \"parent\", None)\n        if span_parent is not None:\n            setter.set(\n                carrier,\n                self.PARENT_SPAN_ID_KEY,\n                format_span_id(span_parent.span_id),\n            )\n        setter.set(carrier, self.SAMPLED_KEY, \"1\" if sampled else \"0\")\n\n    @property\n    def fields(self) -> typing.Set[str]:\n        return {\n            self.TRACE_ID_KEY,\n            self.SPAN_ID_KEY,\n            self.PARENT_SPAN_ID_KEY,\n            self.SAMPLED_KEY,\n        }\n\n\nclass B3SingleFormat(B3MultiFormat):\n    \"\"\"Propagator for the B3 HTTP single-header format.\n\n    See: https://github.com/openzipkin/b3-propagation\n         https://github.com/openzipkin/b3-propagation#single-header\n    \"\"\"\n\n    def inject(\n        self,\n        carrier: CarrierT,\n        context: typing.Optional[Context] = None,\n        setter: Setter = default_setter,\n    ) -> None:\n        span = trace.get_current_span(context=context)\n\n        span_context = span.get_span_context()\n        if span_context == trace.INVALID_SPAN_CONTEXT:\n            return\n\n        sampled = (trace.TraceFlags.SAMPLED & span_context.trace_flags) != 0\n\n        fields = [\n            format_trace_id(span_context.trace_id),\n            format_span_id(span_context.span_id),\n            \"1\" if sampled else \"0\",\n        ]\n\n        span_parent = getattr(span, \"parent\", None)\n        if span_parent:\n            fields.append(format_span_id(span_parent.span_id))\n\n        setter.set(carrier, self.SINGLE_HEADER_KEY, \"-\".join(fields))\n\n    @property\n    def fields(self) -> typing.Set[str]:\n        return {self.SINGLE_HEADER_KEY}\n\n\nclass B3Format(B3MultiFormat):\n    @deprecated(\n        version=\"1.2.0\",\n        reason=\"B3Format is deprecated in favor of B3MultiFormat\",\n    )\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n\n\ndef _extract_first_element(\n    items: typing.Iterable[CarrierT],\n) -> typing.Optional[CarrierT]:\n    if items is None:\n        return None\n    return next(iter(items), None)\n", "path": "propagator/opentelemetry-propagator-b3/src/opentelemetry/propagators/b3/__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\nimport typing\nfrom re import compile as re_compile\n\nfrom deprecated import deprecated\n\nfrom opentelemetry import trace\nfrom opentelemetry.context import Context\nfrom opentelemetry.propagators.textmap import (\n    CarrierT,\n    Getter,\n    Setter,\n    TextMapPropagator,\n    default_getter,\n    default_setter,\n)\nfrom opentelemetry.trace import format_span_id, format_trace_id\n\n\nclass B3MultiFormat(TextMapPropagator):\n    \"\"\"Propagator for the B3 HTTP multi-header format.\n\n    See: https://github.com/openzipkin/b3-propagation\n         https://github.com/openzipkin/b3-propagation#multiple-headers\n    \"\"\"\n\n    SINGLE_HEADER_KEY = \"b3\"\n    TRACE_ID_KEY = \"x-b3-traceid\"\n    SPAN_ID_KEY = \"x-b3-spanid\"\n    SAMPLED_KEY = \"x-b3-sampled\"\n    FLAGS_KEY = \"x-b3-flags\"\n    _SAMPLE_PROPAGATE_VALUES = set([\"1\", \"True\", \"true\", \"d\"])\n    _trace_id_regex = re_compile(r\"[\\da-fA-F]{16}|[\\da-fA-F]{32}\")\n    _span_id_regex = re_compile(r\"[\\da-fA-F]{16}\")\n\n    def extract(\n        self,\n        carrier: CarrierT,\n        context: typing.Optional[Context] = None,\n        getter: Getter = default_getter,\n    ) -> Context:\n        if context is None:\n            context = Context()\n        trace_id = trace.INVALID_TRACE_ID\n        span_id = trace.INVALID_SPAN_ID\n        sampled = \"0\"\n        flags = None\n\n        single_header = _extract_first_element(\n            getter.get(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            trace_id = (\n                _extract_first_element(getter.get(carrier, self.TRACE_ID_KEY))\n                or trace_id\n            )\n            span_id = (\n                _extract_first_element(getter.get(carrier, self.SPAN_ID_KEY))\n                or span_id\n            )\n            sampled = (\n                _extract_first_element(getter.get(carrier, self.SAMPLED_KEY))\n                or sampled\n            )\n            flags = (\n                _extract_first_element(getter.get(carrier, self.FLAGS_KEY))\n                or flags\n            )\n\n        if (\n            trace_id == trace.INVALID_TRACE_ID\n            or span_id == trace.INVALID_SPAN_ID\n            or self._trace_id_regex.fullmatch(trace_id) is None\n            or self._span_id_regex.fullmatch(span_id) is None\n        ):\n            return context\n\n        trace_id = int(trace_id, 16)\n        span_id = int(span_id, 16)\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\n        return trace.set_span_in_context(\n            trace.NonRecordingSpan(\n                trace.SpanContext(\n                    # trace an span ids are encoded in hex, so must be converted\n                    trace_id=trace_id,\n                    span_id=span_id,\n                    is_remote=True,\n                    trace_flags=trace.TraceFlags(options),\n                    trace_state=trace.TraceState(),\n                )\n            ),\n            context,\n        )\n\n    def inject(\n        self,\n        carrier: CarrierT,\n        context: typing.Optional[Context] = None,\n        setter: Setter = default_setter,\n    ) -> None:\n        span = trace.get_current_span(context=context)\n\n        span_context = span.get_span_context()\n        if span_context == trace.INVALID_SPAN_CONTEXT:\n            return\n\n        sampled = (trace.TraceFlags.SAMPLED & span_context.trace_flags) != 0\n        setter.set(\n            carrier,\n            self.TRACE_ID_KEY,\n            format_trace_id(span_context.trace_id),\n        )\n        setter.set(\n            carrier, self.SPAN_ID_KEY, format_span_id(span_context.span_id)\n        )\n        setter.set(carrier, self.SAMPLED_KEY, \"1\" if sampled else \"0\")\n\n    @property\n    def fields(self) -> typing.Set[str]:\n        return {\n            self.TRACE_ID_KEY,\n            self.SPAN_ID_KEY,\n            self.SAMPLED_KEY,\n        }\n\n\nclass B3SingleFormat(B3MultiFormat):\n    \"\"\"Propagator for the B3 HTTP single-header format.\n\n    See: https://github.com/openzipkin/b3-propagation\n         https://github.com/openzipkin/b3-propagation#single-header\n    \"\"\"\n\n    def inject(\n        self,\n        carrier: CarrierT,\n        context: typing.Optional[Context] = None,\n        setter: Setter = default_setter,\n    ) -> None:\n        span = trace.get_current_span(context=context)\n\n        span_context = span.get_span_context()\n        if span_context == trace.INVALID_SPAN_CONTEXT:\n            return\n\n        sampled = (trace.TraceFlags.SAMPLED & span_context.trace_flags) != 0\n\n        fields = [\n            format_trace_id(span_context.trace_id),\n            format_span_id(span_context.span_id),\n            \"1\" if sampled else \"0\",\n        ]\n\n        setter.set(carrier, self.SINGLE_HEADER_KEY, \"-\".join(fields))\n\n    @property\n    def fields(self) -> typing.Set[str]:\n        return {self.SINGLE_HEADER_KEY}\n\n\nclass B3Format(B3MultiFormat):\n    @deprecated(\n        version=\"1.2.0\",\n        reason=\"B3Format is deprecated in favor of B3MultiFormat\",\n    )\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n\n\ndef _extract_first_element(\n    items: typing.Iterable[CarrierT],\n) -> typing.Optional[CarrierT]:\n    if items is None:\n        return None\n    return next(iter(items), None)\n", "path": "propagator/opentelemetry-propagator-b3/src/opentelemetry/propagators/b3/__init__.py"}]}