We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
`st.metric` should have `label_visibility` parameter
We had that in the original spec but probably forgot it during implementation. Let's fix it. Not super urgent but would be good to do soon so we don't forget. 

---

Community voting on feature requests enables the Streamlit team to understand which features are most important to our users.

**If you'd like the Streamlit team to prioritize this feature request, please use the 👍 (thumbs up emoji) reaction in response to the initial post.**


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `lib/streamlit/elements/metric.py`
Content:
```
1 # Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022)
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 from dataclasses import dataclass
16 from textwrap import dedent
17 from typing import TYPE_CHECKING, Optional, Union, cast
18 
19 from typing_extensions import Literal, TypeAlias
20 
21 from streamlit.errors import StreamlitAPIException
22 from streamlit.proto.Metric_pb2 import Metric as MetricProto
23 from streamlit.runtime.metrics_util import gather_metrics
24 from streamlit.string_util import clean_text
25 
26 if TYPE_CHECKING:
27     import numpy as np
28 
29     from streamlit.delta_generator import DeltaGenerator
30 
31 
32 Value: TypeAlias = Union["np.integer", "np.floating", float, int, str, None]
33 Delta: TypeAlias = Union[float, int, str, None]
34 DeltaColor: TypeAlias = Literal["normal", "inverse", "off"]
35 
36 
37 @dataclass(frozen=True)
38 class MetricColorAndDirection:
39     color: "MetricProto.MetricColor.ValueType"
40     direction: "MetricProto.MetricDirection.ValueType"
41 
42 
43 class MetricMixin:
44     @gather_metrics("metric")
45     def metric(
46         self,
47         label: str,
48         value: Value,
49         delta: Delta = None,
50         delta_color: DeltaColor = "normal",
51         help: Optional[str] = None,
52     ) -> "DeltaGenerator":
53         """Display a metric in big bold font, with an optional indicator of how the metric changed.
54 
55         Tip: If you want to display a large number, it may be a good idea to
56         shorten it using packages like `millify <https://github.com/azaitsev/millify>`_
57         or `numerize <https://github.com/davidsa03/numerize>`_. E.g. ``1234`` can be
58         displayed as ``1.2k`` using ``st.metric("Short number", millify(1234))``.
59 
60         Parameters
61         ----------
62         label : str
63             The header or title for the metric. The label can optionally contain
64             Markdown and supports the following elements: Bold, Italics,
65             Strikethroughs, Inline Code, Emojis, and Links.
66         value : int, float, str, or None
67              Value of the metric. None is rendered as a long dash.
68         delta : int, float, str, or None
69             Indicator of how the metric changed, rendered with an arrow below
70             the metric. If delta is negative (int/float) or starts with a minus
71             sign (str), the arrow points down and the text is red; else the
72             arrow points up and the text is green. If None (default), no delta
73             indicator is shown.
74         delta_color : str
75              If "normal" (default), the delta indicator is shown as described
76              above. If "inverse", it is red when positive and green when
77              negative. This is useful when a negative change is considered
78              good, e.g. if cost decreased. If "off", delta is  shown in gray
79              regardless of its value.
80         help : str
81             An optional tooltip that gets displayed next to the metric label.
82 
83         Example
84         -------
85         >>> st.metric(label="Temperature", value="70 °F", delta="1.2 °F")
86 
87         .. output::
88             https://doc-metric-example1.streamlitapp.com/
89             height: 210px
90 
91         ``st.metric`` looks especially nice in combination with ``st.columns``:
92 
93         >>> col1, col2, col3 = st.columns(3)
94         >>> col1.metric("Temperature", "70 °F", "1.2 °F")
95         >>> col2.metric("Wind", "9 mph", "-8%")
96         >>> col3.metric("Humidity", "86%", "4%")
97 
98         .. output::
99             https://doc-metric-example2.streamlitapp.com/
100             height: 210px
101 
102         The delta indicator color can also be inverted or turned off:
103 
104         >>> st.metric(label="Gas price", value=4, delta=-0.5,
105         ...     delta_color="inverse")
106         >>>
107         >>> st.metric(label="Active developers", value=123, delta=123,
108         ...     delta_color="off")
109 
110         .. output::
111             https://doc-metric-example3.streamlitapp.com/
112             height: 320px
113 
114         """
115         metric_proto = MetricProto()
116         metric_proto.body = self.parse_value(value)
117         metric_proto.label = self.parse_label(label)
118         metric_proto.delta = self.parse_delta(delta)
119         if help is not None:
120             metric_proto.help = dedent(help)
121 
122         color_and_direction = self.determine_delta_color_and_direction(
123             cast(DeltaColor, clean_text(delta_color)), delta
124         )
125         metric_proto.color = color_and_direction.color
126         metric_proto.direction = color_and_direction.direction
127 
128         return self.dg._enqueue("metric", metric_proto)
129 
130     @staticmethod
131     def parse_label(label: str) -> str:
132         if not isinstance(label, str):
133             raise TypeError(
134                 f"'{str(label)}' is of type {str(type(label))}, which is not an accepted type."
135                 " label only accepts: str. Please convert the label to an accepted type."
136             )
137         return label
138 
139     @staticmethod
140     def parse_value(value: Value) -> str:
141         if value is None:
142             return "—"
143         if isinstance(value, int) or isinstance(value, float) or isinstance(value, str):
144             return str(value)
145         elif hasattr(value, "item"):
146             # Add support for numpy values (e.g. int16, float64, etc.)
147             try:
148                 # Item could also be just a variable, so we use try, except
149                 if isinstance(value.item(), float) or isinstance(value.item(), int):
150                     return str(value.item())
151             except Exception:
152                 # If the numpy item is not a valid value, the TypeError below will be raised.
153                 pass
154 
155         raise TypeError(
156             f"'{str(value)}' is of type {str(type(value))}, which is not an accepted type."
157             " value only accepts: int, float, str, or None."
158             " Please convert the value to an accepted type."
159         )
160 
161     @staticmethod
162     def parse_delta(delta: Delta) -> str:
163         if delta is None or delta == "":
164             return ""
165         if isinstance(delta, str):
166             return dedent(delta)
167         elif isinstance(delta, int) or isinstance(delta, float):
168             return str(delta)
169         else:
170             raise TypeError(
171                 f"'{str(delta)}' is of type {str(type(delta))}, which is not an accepted type."
172                 " delta only accepts: int, float, str, or None."
173                 " Please convert the value to an accepted type."
174             )
175 
176     def determine_delta_color_and_direction(
177         self,
178         delta_color: DeltaColor,
179         delta: Delta,
180     ) -> MetricColorAndDirection:
181         if delta_color not in {"normal", "inverse", "off"}:
182             raise StreamlitAPIException(
183                 f"'{str(delta_color)}' is not an accepted value. delta_color only accepts: "
184                 "'normal', 'inverse', or 'off'"
185             )
186 
187         if delta is None or delta == "":
188             return MetricColorAndDirection(
189                 color=MetricProto.MetricColor.GRAY,
190                 direction=MetricProto.MetricDirection.NONE,
191             )
192 
193         if self.is_negative(delta):
194             if delta_color == "normal":
195                 cd_color = MetricProto.MetricColor.RED
196             elif delta_color == "inverse":
197                 cd_color = MetricProto.MetricColor.GREEN
198             else:
199                 cd_color = MetricProto.MetricColor.GRAY
200             cd_direction = MetricProto.MetricDirection.DOWN
201         else:
202             if delta_color == "normal":
203                 cd_color = MetricProto.MetricColor.GREEN
204             elif delta_color == "inverse":
205                 cd_color = MetricProto.MetricColor.RED
206             else:
207                 cd_color = MetricProto.MetricColor.GRAY
208             cd_direction = MetricProto.MetricDirection.UP
209 
210         return MetricColorAndDirection(
211             color=cd_color,
212             direction=cd_direction,
213         )
214 
215     @staticmethod
216     def is_negative(delta: Delta) -> bool:
217         return dedent(str(delta)).startswith("-")
218 
219     @property
220     def dg(self) -> "DeltaGenerator":
221         return cast("DeltaGenerator", self)
222
```

Path: `e2e/scripts/st_metric.py`
Content:
```
1 # Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022)
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 streamlit as st
16 
17 col1, col2, col3 = st.columns(3)
18 
19 with col1:
20     st.metric("User growth", 123, 123, "normal")
21 with col2:
22     st.metric("S&P 500", -4.56, -50)
23 with col3:
24     st.metric("Apples I've eaten", "23k", " -20", "off")
25 
26 " "
27 
28 col1, col2, col3 = st.columns(3)
29 
30 with col1:
31     st.selectbox("Pick one", [])
32 with col2:
33     st.metric("Test 2", -4.56, 1.23, "inverse")
34 with col3:
35     st.slider("Pick another")
36
```
--- 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/e2e/scripts/st_metric.py b/e2e/scripts/st_metric.py
--- a/e2e/scripts/st_metric.py
+++ b/e2e/scripts/st_metric.py
@@ -33,3 +33,11 @@
     st.metric("Test 2", -4.56, 1.23, "inverse")
 with col3:
     st.slider("Pick another")
+
+
+with col1:
+    st.metric("Test 3", -4.56, 1.23, label_visibility="visible")
+with col2:
+    st.metric("Test 4", -4.56, 1.23, label_visibility="hidden")
+with col3:
+    st.metric("Test 5", -4.56, 1.23, label_visibility="collapsed")
diff --git a/lib/streamlit/elements/metric.py b/lib/streamlit/elements/metric.py
--- a/lib/streamlit/elements/metric.py
+++ b/lib/streamlit/elements/metric.py
@@ -18,10 +18,12 @@
 
 from typing_extensions import Literal, TypeAlias
 
+from streamlit.elements.utils import get_label_visibility_proto_value
 from streamlit.errors import StreamlitAPIException
 from streamlit.proto.Metric_pb2 import Metric as MetricProto
 from streamlit.runtime.metrics_util import gather_metrics
 from streamlit.string_util import clean_text
+from streamlit.type_util import LabelVisibility, maybe_raise_label_warnings
 
 if TYPE_CHECKING:
     import numpy as np
@@ -49,6 +51,7 @@
         delta: Delta = None,
         delta_color: DeltaColor = "normal",
         help: Optional[str] = None,
+        label_visibility: LabelVisibility = "visible",
     ) -> "DeltaGenerator":
         """Display a metric in big bold font, with an optional indicator of how the metric changed.
 
@@ -79,6 +82,11 @@
              regardless of its value.
         help : str
             An optional tooltip that gets displayed next to the metric label.
+        label_visibility : "visible" or "hidden" or "collapsed"
+            The visibility of the label. If "hidden", the label doesn't show but there
+            is still empty space for it (equivalent to label="").
+            If "collapsed", both the label and the space are removed. Default is
+            "visible". This argument can only be supplied by keyword.
 
         Example
         -------
@@ -112,6 +120,8 @@
             height: 320px
 
         """
+        maybe_raise_label_warnings(label, label_visibility)
+
         metric_proto = MetricProto()
         metric_proto.body = self.parse_value(value)
         metric_proto.label = self.parse_label(label)
@@ -124,6 +134,9 @@
         )
         metric_proto.color = color_and_direction.color
         metric_proto.direction = color_and_direction.direction
+        metric_proto.label_visibility.value = get_label_visibility_proto_value(
+            label_visibility
+        )
 
         return self.dg._enqueue("metric", metric_proto)

{"golden_diff": "diff --git a/e2e/scripts/st_metric.py b/e2e/scripts/st_metric.py\n--- a/e2e/scripts/st_metric.py\n+++ b/e2e/scripts/st_metric.py\n@@ -33,3 +33,11 @@\n     st.metric(\"Test 2\", -4.56, 1.23, \"inverse\")\n with col3:\n     st.slider(\"Pick another\")\n+\n+\n+with col1:\n+    st.metric(\"Test 3\", -4.56, 1.23, label_visibility=\"visible\")\n+with col2:\n+    st.metric(\"Test 4\", -4.56, 1.23, label_visibility=\"hidden\")\n+with col3:\n+    st.metric(\"Test 5\", -4.56, 1.23, label_visibility=\"collapsed\")\ndiff --git a/lib/streamlit/elements/metric.py b/lib/streamlit/elements/metric.py\n--- a/lib/streamlit/elements/metric.py\n+++ b/lib/streamlit/elements/metric.py\n@@ -18,10 +18,12 @@\n \n from typing_extensions import Literal, TypeAlias\n \n+from streamlit.elements.utils import get_label_visibility_proto_value\n from streamlit.errors import StreamlitAPIException\n from streamlit.proto.Metric_pb2 import Metric as MetricProto\n from streamlit.runtime.metrics_util import gather_metrics\n from streamlit.string_util import clean_text\n+from streamlit.type_util import LabelVisibility, maybe_raise_label_warnings\n \n if TYPE_CHECKING:\n     import numpy as np\n@@ -49,6 +51,7 @@\n         delta: Delta = None,\n         delta_color: DeltaColor = \"normal\",\n         help: Optional[str] = None,\n+        label_visibility: LabelVisibility = \"visible\",\n     ) -> \"DeltaGenerator\":\n         \"\"\"Display a metric in big bold font, with an optional indicator of how the metric changed.\n \n@@ -79,6 +82,11 @@\n              regardless of its value.\n         help : str\n             An optional tooltip that gets displayed next to the metric label.\n+        label_visibility : \"visible\" or \"hidden\" or \"collapsed\"\n+            The visibility of the label. If \"hidden\", the label doesn't show but there\n+            is still empty space for it (equivalent to label=\"\").\n+            If \"collapsed\", both the label and the space are removed. Default is\n+            \"visible\". This argument can only be supplied by keyword.\n \n         Example\n         -------\n@@ -112,6 +120,8 @@\n             height: 320px\n \n         \"\"\"\n+        maybe_raise_label_warnings(label, label_visibility)\n+\n         metric_proto = MetricProto()\n         metric_proto.body = self.parse_value(value)\n         metric_proto.label = self.parse_label(label)\n@@ -124,6 +134,9 @@\n         )\n         metric_proto.color = color_and_direction.color\n         metric_proto.direction = color_and_direction.direction\n+        metric_proto.label_visibility.value = get_label_visibility_proto_value(\n+            label_visibility\n+        )\n \n         return self.dg._enqueue(\"metric\", metric_proto)\n", "issue": "`st.metric` should have `label_visibility` parameter\nWe had that in the original spec but probably forgot it during implementation. Let's fix it. Not super urgent but would be good to do soon so we don't forget. \r\n\r\n---\r\n\r\nCommunity voting on feature requests enables the Streamlit team to understand which features are most important to our users.\r\n\r\n**If you'd like the Streamlit team to prioritize this feature request, please use the \ud83d\udc4d (thumbs up emoji) reaction in response to the initial post.**\r\n\n", "before_files": [{"content": "# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022)\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\nfrom dataclasses import dataclass\nfrom textwrap import dedent\nfrom typing import TYPE_CHECKING, Optional, Union, cast\n\nfrom typing_extensions import Literal, TypeAlias\n\nfrom streamlit.errors import StreamlitAPIException\nfrom streamlit.proto.Metric_pb2 import Metric as MetricProto\nfrom streamlit.runtime.metrics_util import gather_metrics\nfrom streamlit.string_util import clean_text\n\nif TYPE_CHECKING:\n    import numpy as np\n\n    from streamlit.delta_generator import DeltaGenerator\n\n\nValue: TypeAlias = Union[\"np.integer\", \"np.floating\", float, int, str, None]\nDelta: TypeAlias = Union[float, int, str, None]\nDeltaColor: TypeAlias = Literal[\"normal\", \"inverse\", \"off\"]\n\n\n@dataclass(frozen=True)\nclass MetricColorAndDirection:\n    color: \"MetricProto.MetricColor.ValueType\"\n    direction: \"MetricProto.MetricDirection.ValueType\"\n\n\nclass MetricMixin:\n    @gather_metrics(\"metric\")\n    def metric(\n        self,\n        label: str,\n        value: Value,\n        delta: Delta = None,\n        delta_color: DeltaColor = \"normal\",\n        help: Optional[str] = None,\n    ) -> \"DeltaGenerator\":\n        \"\"\"Display a metric in big bold font, with an optional indicator of how the metric changed.\n\n        Tip: If you want to display a large number, it may be a good idea to\n        shorten it using packages like `millify <https://github.com/azaitsev/millify>`_\n        or `numerize <https://github.com/davidsa03/numerize>`_. E.g. ``1234`` can be\n        displayed as ``1.2k`` using ``st.metric(\"Short number\", millify(1234))``.\n\n        Parameters\n        ----------\n        label : str\n            The header or title for the metric. The label can optionally contain\n            Markdown and supports the following elements: Bold, Italics,\n            Strikethroughs, Inline Code, Emojis, and Links.\n        value : int, float, str, or None\n             Value of the metric. None is rendered as a long dash.\n        delta : int, float, str, or None\n            Indicator of how the metric changed, rendered with an arrow below\n            the metric. If delta is negative (int/float) or starts with a minus\n            sign (str), the arrow points down and the text is red; else the\n            arrow points up and the text is green. If None (default), no delta\n            indicator is shown.\n        delta_color : str\n             If \"normal\" (default), the delta indicator is shown as described\n             above. If \"inverse\", it is red when positive and green when\n             negative. This is useful when a negative change is considered\n             good, e.g. if cost decreased. If \"off\", delta is  shown in gray\n             regardless of its value.\n        help : str\n            An optional tooltip that gets displayed next to the metric label.\n\n        Example\n        -------\n        >>> st.metric(label=\"Temperature\", value=\"70 \u00b0F\", delta=\"1.2 \u00b0F\")\n\n        .. output::\n            https://doc-metric-example1.streamlitapp.com/\n            height: 210px\n\n        ``st.metric`` looks especially nice in combination with ``st.columns``:\n\n        >>> col1, col2, col3 = st.columns(3)\n        >>> col1.metric(\"Temperature\", \"70 \u00b0F\", \"1.2 \u00b0F\")\n        >>> col2.metric(\"Wind\", \"9 mph\", \"-8%\")\n        >>> col3.metric(\"Humidity\", \"86%\", \"4%\")\n\n        .. output::\n            https://doc-metric-example2.streamlitapp.com/\n            height: 210px\n\n        The delta indicator color can also be inverted or turned off:\n\n        >>> st.metric(label=\"Gas price\", value=4, delta=-0.5,\n        ...     delta_color=\"inverse\")\n        >>>\n        >>> st.metric(label=\"Active developers\", value=123, delta=123,\n        ...     delta_color=\"off\")\n\n        .. output::\n            https://doc-metric-example3.streamlitapp.com/\n            height: 320px\n\n        \"\"\"\n        metric_proto = MetricProto()\n        metric_proto.body = self.parse_value(value)\n        metric_proto.label = self.parse_label(label)\n        metric_proto.delta = self.parse_delta(delta)\n        if help is not None:\n            metric_proto.help = dedent(help)\n\n        color_and_direction = self.determine_delta_color_and_direction(\n            cast(DeltaColor, clean_text(delta_color)), delta\n        )\n        metric_proto.color = color_and_direction.color\n        metric_proto.direction = color_and_direction.direction\n\n        return self.dg._enqueue(\"metric\", metric_proto)\n\n    @staticmethod\n    def parse_label(label: str) -> str:\n        if not isinstance(label, str):\n            raise TypeError(\n                f\"'{str(label)}' is of type {str(type(label))}, which is not an accepted type.\"\n                \" label only accepts: str. Please convert the label to an accepted type.\"\n            )\n        return label\n\n    @staticmethod\n    def parse_value(value: Value) -> str:\n        if value is None:\n            return \"\u2014\"\n        if isinstance(value, int) or isinstance(value, float) or isinstance(value, str):\n            return str(value)\n        elif hasattr(value, \"item\"):\n            # Add support for numpy values (e.g. int16, float64, etc.)\n            try:\n                # Item could also be just a variable, so we use try, except\n                if isinstance(value.item(), float) or isinstance(value.item(), int):\n                    return str(value.item())\n            except Exception:\n                # If the numpy item is not a valid value, the TypeError below will be raised.\n                pass\n\n        raise TypeError(\n            f\"'{str(value)}' is of type {str(type(value))}, which is not an accepted type.\"\n            \" value only accepts: int, float, str, or None.\"\n            \" Please convert the value to an accepted type.\"\n        )\n\n    @staticmethod\n    def parse_delta(delta: Delta) -> str:\n        if delta is None or delta == \"\":\n            return \"\"\n        if isinstance(delta, str):\n            return dedent(delta)\n        elif isinstance(delta, int) or isinstance(delta, float):\n            return str(delta)\n        else:\n            raise TypeError(\n                f\"'{str(delta)}' is of type {str(type(delta))}, which is not an accepted type.\"\n                \" delta only accepts: int, float, str, or None.\"\n                \" Please convert the value to an accepted type.\"\n            )\n\n    def determine_delta_color_and_direction(\n        self,\n        delta_color: DeltaColor,\n        delta: Delta,\n    ) -> MetricColorAndDirection:\n        if delta_color not in {\"normal\", \"inverse\", \"off\"}:\n            raise StreamlitAPIException(\n                f\"'{str(delta_color)}' is not an accepted value. delta_color only accepts: \"\n                \"'normal', 'inverse', or 'off'\"\n            )\n\n        if delta is None or delta == \"\":\n            return MetricColorAndDirection(\n                color=MetricProto.MetricColor.GRAY,\n                direction=MetricProto.MetricDirection.NONE,\n            )\n\n        if self.is_negative(delta):\n            if delta_color == \"normal\":\n                cd_color = MetricProto.MetricColor.RED\n            elif delta_color == \"inverse\":\n                cd_color = MetricProto.MetricColor.GREEN\n            else:\n                cd_color = MetricProto.MetricColor.GRAY\n            cd_direction = MetricProto.MetricDirection.DOWN\n        else:\n            if delta_color == \"normal\":\n                cd_color = MetricProto.MetricColor.GREEN\n            elif delta_color == \"inverse\":\n                cd_color = MetricProto.MetricColor.RED\n            else:\n                cd_color = MetricProto.MetricColor.GRAY\n            cd_direction = MetricProto.MetricDirection.UP\n\n        return MetricColorAndDirection(\n            color=cd_color,\n            direction=cd_direction,\n        )\n\n    @staticmethod\n    def is_negative(delta: Delta) -> bool:\n        return dedent(str(delta)).startswith(\"-\")\n\n    @property\n    def dg(self) -> \"DeltaGenerator\":\n        return cast(\"DeltaGenerator\", self)\n", "path": "lib/streamlit/elements/metric.py"}, {"content": "# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022)\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 streamlit as st\n\ncol1, col2, col3 = st.columns(3)\n\nwith col1:\n    st.metric(\"User growth\", 123, 123, \"normal\")\nwith col2:\n    st.metric(\"S&P 500\", -4.56, -50)\nwith col3:\n    st.metric(\"Apples I've eaten\", \"23k\", \" -20\", \"off\")\n\n\" \"\n\ncol1, col2, col3 = st.columns(3)\n\nwith col1:\n    st.selectbox(\"Pick one\", [])\nwith col2:\n    st.metric(\"Test 2\", -4.56, 1.23, \"inverse\")\nwith col3:\n    st.slider(\"Pick another\")\n", "path": "e2e/scripts/st_metric.py"}], "after_files": [{"content": "# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022)\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\nfrom dataclasses import dataclass\nfrom textwrap import dedent\nfrom typing import TYPE_CHECKING, Optional, Union, cast\n\nfrom typing_extensions import Literal, TypeAlias\n\nfrom streamlit.elements.utils import get_label_visibility_proto_value\nfrom streamlit.errors import StreamlitAPIException\nfrom streamlit.proto.Metric_pb2 import Metric as MetricProto\nfrom streamlit.runtime.metrics_util import gather_metrics\nfrom streamlit.string_util import clean_text\nfrom streamlit.type_util import LabelVisibility, maybe_raise_label_warnings\n\nif TYPE_CHECKING:\n    import numpy as np\n\n    from streamlit.delta_generator import DeltaGenerator\n\n\nValue: TypeAlias = Union[\"np.integer\", \"np.floating\", float, int, str, None]\nDelta: TypeAlias = Union[float, int, str, None]\nDeltaColor: TypeAlias = Literal[\"normal\", \"inverse\", \"off\"]\n\n\n@dataclass(frozen=True)\nclass MetricColorAndDirection:\n    color: \"MetricProto.MetricColor.ValueType\"\n    direction: \"MetricProto.MetricDirection.ValueType\"\n\n\nclass MetricMixin:\n    @gather_metrics(\"metric\")\n    def metric(\n        self,\n        label: str,\n        value: Value,\n        delta: Delta = None,\n        delta_color: DeltaColor = \"normal\",\n        help: Optional[str] = None,\n        label_visibility: LabelVisibility = \"visible\",\n    ) -> \"DeltaGenerator\":\n        \"\"\"Display a metric in big bold font, with an optional indicator of how the metric changed.\n\n        Tip: If you want to display a large number, it may be a good idea to\n        shorten it using packages like `millify <https://github.com/azaitsev/millify>`_\n        or `numerize <https://github.com/davidsa03/numerize>`_. E.g. ``1234`` can be\n        displayed as ``1.2k`` using ``st.metric(\"Short number\", millify(1234))``.\n\n        Parameters\n        ----------\n        label : str\n            The header or title for the metric. The label can optionally contain\n            Markdown and supports the following elements: Bold, Italics,\n            Strikethroughs, Inline Code, Emojis, and Links.\n        value : int, float, str, or None\n             Value of the metric. None is rendered as a long dash.\n        delta : int, float, str, or None\n            Indicator of how the metric changed, rendered with an arrow below\n            the metric. If delta is negative (int/float) or starts with a minus\n            sign (str), the arrow points down and the text is red; else the\n            arrow points up and the text is green. If None (default), no delta\n            indicator is shown.\n        delta_color : str\n             If \"normal\" (default), the delta indicator is shown as described\n             above. If \"inverse\", it is red when positive and green when\n             negative. This is useful when a negative change is considered\n             good, e.g. if cost decreased. If \"off\", delta is  shown in gray\n             regardless of its value.\n        help : str\n            An optional tooltip that gets displayed next to the metric label.\n        label_visibility : \"visible\" or \"hidden\" or \"collapsed\"\n            The visibility of the label. If \"hidden\", the label doesn't show but there\n            is still empty space for it (equivalent to label=\"\").\n            If \"collapsed\", both the label and the space are removed. Default is\n            \"visible\". This argument can only be supplied by keyword.\n\n        Example\n        -------\n        >>> st.metric(label=\"Temperature\", value=\"70 \u00b0F\", delta=\"1.2 \u00b0F\")\n\n        .. output::\n            https://doc-metric-example1.streamlitapp.com/\n            height: 210px\n\n        ``st.metric`` looks especially nice in combination with ``st.columns``:\n\n        >>> col1, col2, col3 = st.columns(3)\n        >>> col1.metric(\"Temperature\", \"70 \u00b0F\", \"1.2 \u00b0F\")\n        >>> col2.metric(\"Wind\", \"9 mph\", \"-8%\")\n        >>> col3.metric(\"Humidity\", \"86%\", \"4%\")\n\n        .. output::\n            https://doc-metric-example2.streamlitapp.com/\n            height: 210px\n\n        The delta indicator color can also be inverted or turned off:\n\n        >>> st.metric(label=\"Gas price\", value=4, delta=-0.5,\n        ...     delta_color=\"inverse\")\n        >>>\n        >>> st.metric(label=\"Active developers\", value=123, delta=123,\n        ...     delta_color=\"off\")\n\n        .. output::\n            https://doc-metric-example3.streamlitapp.com/\n            height: 320px\n\n        \"\"\"\n        maybe_raise_label_warnings(label, label_visibility)\n\n        metric_proto = MetricProto()\n        metric_proto.body = self.parse_value(value)\n        metric_proto.label = self.parse_label(label)\n        metric_proto.delta = self.parse_delta(delta)\n        if help is not None:\n            metric_proto.help = dedent(help)\n\n        color_and_direction = self.determine_delta_color_and_direction(\n            cast(DeltaColor, clean_text(delta_color)), delta\n        )\n        metric_proto.color = color_and_direction.color\n        metric_proto.direction = color_and_direction.direction\n        metric_proto.label_visibility.value = get_label_visibility_proto_value(\n            label_visibility\n        )\n\n        return self.dg._enqueue(\"metric\", metric_proto)\n\n    @staticmethod\n    def parse_label(label: str) -> str:\n        if not isinstance(label, str):\n            raise TypeError(\n                f\"'{str(label)}' is of type {str(type(label))}, which is not an accepted type.\"\n                \" label only accepts: str. Please convert the label to an accepted type.\"\n            )\n        return label\n\n    @staticmethod\n    def parse_value(value: Value) -> str:\n        if value is None:\n            return \"\u2014\"\n        if isinstance(value, int) or isinstance(value, float) or isinstance(value, str):\n            return str(value)\n        elif hasattr(value, \"item\"):\n            # Add support for numpy values (e.g. int16, float64, etc.)\n            try:\n                # Item could also be just a variable, so we use try, except\n                if isinstance(value.item(), float) or isinstance(value.item(), int):\n                    return str(value.item())\n            except Exception:\n                # If the numpy item is not a valid value, the TypeError below will be raised.\n                pass\n\n        raise TypeError(\n            f\"'{str(value)}' is of type {str(type(value))}, which is not an accepted type.\"\n            \" value only accepts: int, float, str, or None.\"\n            \" Please convert the value to an accepted type.\"\n        )\n\n    @staticmethod\n    def parse_delta(delta: Delta) -> str:\n        if delta is None or delta == \"\":\n            return \"\"\n        if isinstance(delta, str):\n            return dedent(delta)\n        elif isinstance(delta, int) or isinstance(delta, float):\n            return str(delta)\n        else:\n            raise TypeError(\n                f\"'{str(delta)}' is of type {str(type(delta))}, which is not an accepted type.\"\n                \" delta only accepts: int, float, str, or None.\"\n                \" Please convert the value to an accepted type.\"\n            )\n\n    def determine_delta_color_and_direction(\n        self,\n        delta_color: DeltaColor,\n        delta: Delta,\n    ) -> MetricColorAndDirection:\n        if delta_color not in {\"normal\", \"inverse\", \"off\"}:\n            raise StreamlitAPIException(\n                f\"'{str(delta_color)}' is not an accepted value. delta_color only accepts: \"\n                \"'normal', 'inverse', or 'off'\"\n            )\n\n        if delta is None or delta == \"\":\n            return MetricColorAndDirection(\n                color=MetricProto.MetricColor.GRAY,\n                direction=MetricProto.MetricDirection.NONE,\n            )\n\n        if self.is_negative(delta):\n            if delta_color == \"normal\":\n                cd_color = MetricProto.MetricColor.RED\n            elif delta_color == \"inverse\":\n                cd_color = MetricProto.MetricColor.GREEN\n            else:\n                cd_color = MetricProto.MetricColor.GRAY\n            cd_direction = MetricProto.MetricDirection.DOWN\n        else:\n            if delta_color == \"normal\":\n                cd_color = MetricProto.MetricColor.GREEN\n            elif delta_color == \"inverse\":\n                cd_color = MetricProto.MetricColor.RED\n            else:\n                cd_color = MetricProto.MetricColor.GRAY\n            cd_direction = MetricProto.MetricDirection.UP\n\n        return MetricColorAndDirection(\n            color=cd_color,\n            direction=cd_direction,\n        )\n\n    @staticmethod\n    def is_negative(delta: Delta) -> bool:\n        return dedent(str(delta)).startswith(\"-\")\n\n    @property\n    def dg(self) -> \"DeltaGenerator\":\n        return cast(\"DeltaGenerator\", self)\n", "path": "lib/streamlit/elements/metric.py"}, {"content": "# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022)\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 streamlit as st\n\ncol1, col2, col3 = st.columns(3)\n\nwith col1:\n    st.metric(\"User growth\", 123, 123, \"normal\")\nwith col2:\n    st.metric(\"S&P 500\", -4.56, -50)\nwith col3:\n    st.metric(\"Apples I've eaten\", \"23k\", \" -20\", \"off\")\n\n\" \"\n\ncol1, col2, col3 = st.columns(3)\n\nwith col1:\n    st.selectbox(\"Pick one\", [])\nwith col2:\n    st.metric(\"Test 2\", -4.56, 1.23, \"inverse\")\nwith col3:\n    st.slider(\"Pick another\")\n\n\nwith col1:\n    st.metric(\"Test 3\", -4.56, 1.23, label_visibility=\"visible\")\nwith col2:\n    st.metric(\"Test 4\", -4.56, 1.23, label_visibility=\"hidden\")\nwith col3:\n    st.metric(\"Test 5\", -4.56, 1.23, label_visibility=\"collapsed\")\n", "path": "e2e/scripts/st_metric.py"}]}