We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Remove `webdriver-manager` from `dash[testing]` requirements
This was added in #1801 but wasn't really clear why it was needed, and it reaches out to the internet during its installation (even if installed from a local PyPI mirror) which causes problems for some users.
[BUG] Dash DataTable style_header text_alignment breaks between Dash v2.0.0 and v2.1.0
Production environment is under a customer container hosting environment that hosts docker container in a large corporate environment.  Docker container is setup with rhel 7 (Redhat) with an Apache 2.4 web server.  Python 3.6 is the version of python using pip as the installation for packages.

-  replace the result of `pip list | grep dash` below
```
dash                       2.1.0    
dash-bootstrap-components  1.0.2    
dash-core-components       2.0.0    
dash-html-components       2.0.0    
dash-renderer              1.9.1    
dash-table                 5.0.0
```

-  if frontend related, tell us your Browser, Version and OS

    - OS: MacOS Monterey version 12.2
    - Browser Chrome
    - Version 98.0.4758.80

**Describe the bug**

When using 'text-align': 'center' in the style_header directive within the dash_table.DataTable, under Dash 2.1.0, the headings for the table are not centered, rather they are right aligned, regardless of the setting of the 'text-align' value.  In fact, directly editing the text-align within Chrome's developer tool will not change the alignment.  Changing other attributes (font, color, etc... will work).  

**Expected behavior**

I would expect that when 'text-align': 'center' is specified for the style_header directive within dash_table.DataTable that the headings for the columns specified would be centered above the column.

**Screenshots**

![image](https://user-images.githubusercontent.com/3968562/152881625-b91b2ad5-317c-4ae6-ba90-3e289fcea525.png)

**Additional Information**
I've been able to workaround this issue by reverting to Dash 2.0.0 in my production build, but I have not been able to build a similar working environment, neither in pip nor conda.  My production version is working.  I only reverted to Dash 2.0.0 since it was a very recent release, and then the behavior of the dash_table.DataTable worked correctly.  It was the only change I made to the Docker build.  Now, regardless of whether I use Dash 2.0.0 or Dash 2.1.0, I'm seeing the persistent right alignment of headers in my DataTables.  

I do not know if it will help, but here is an example of code that I saw work under Dash 2.0.0, and then fail once I upgraded to Dash 2.1.0:
```
import pandas as pd
from dash import dcc
# import dash_core_components as dcc
from dash import html
# import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
import plotly.express as px
import time
import random

app = dash.Dash(__name__)

def get_rand_data():
    mylist=[random.randint(1,6) for _ in range(6)]
    return mylist

def build_data(mylist):
    df = pd.DataFrame({
        "Fruit": ["Apples", "Oranges", "Bananas", "Apples", "Oranges", "Bananas"],
        "Amount": mylist,
        "City": ["SF", "SF", "SF", "Montreal", "Montreal", "Montreal"]
    })
    dcc.Store(id='new_data', data=df.to_json())
    return df

def draw_graph(df):
    fig = px.bar(df, x="Fruit", y="Amount", color="City", barmode="group")
    return fig

def get_table():
    data_table =  dash_table.DataTable(
        columns=[
            {"name": ["", "Year"], "id": "year"},
            {"name": ["City", "Montreal"], "id": "montreal"},
            {"name": ["City", "Toronto"], "id": "toronto"},
            {"name": ["City", "Ottawa"], "id": "ottawa"},
            {"name": ["City", "Vancouver"], "id": "vancouver"},
            {"name": ["Climate", "Temperature"], "id": "temp"},
            {"name": ["Climate", "Humidity"], "id": "humidity"},
        ],
        data=[
            {
                "year": i,
                "montreal": i * 10,
                "toronto": i * 100,
                "ottawa": i * -1,
                "vancouver": i * -10,
                "temp": i * -100,
                "humidity": i * 5,
            }
            for i in range(10)
        ],
        style_header={
                'text-align': 'center',
            },
        merge_duplicate_headers=True,
    )
    return data_table


mylist=get_rand_data()
df = build_data(mylist)
fig = draw_graph(df)
data_table = get_table()

refresh_button = dbc.Button('Refresh Data', color="info", className="me-1", id='refresh_button_lmd')

app.layout = html.Div(children=[
    html.H1(children='Hello Dash'),
    refresh_button,
    html.Div(children=[
        data_table
    ]),
    dcc.Store(id='new_data'),
    dcc.Loading(
        id='loading-data',
        children=[
            html.Div(children=[
                dcc.Graph(
                    id='example-graph',
                    figure=fig
                )
            ]
            )
        ],
        type='circle',
    ),
])


@app.callback(Output("example-graph", "figure"),
              Input("new_data", "data"))
def on_data(data):
    df = pd.read_json(data)
    time.sleep(5)
    fig = draw_graph(df)
    return fig


@app.callback(Output('new_data', 'data'),
              Input('refresh_button_lmd', 'n_clicks'))
def new_data(n_clicks):
    if n_clicks is None:
        print("Override Startup")
        mylist = get_rand_data()
        df = build_data(mylist)
        data = df.to_json()
    else:
        print(f'Button was clicked, this is {n_clicks} times.')
        mylist = get_rand_data()
        df = build_data(mylist)
        data=df.to_json()
    return data

if __name__ == '__main__':
    app.run_server(debug=True)
```

I suspect that perhaps an upgrade supporting the move to Dash 2.1.0 might be the issue, and that now that I've moved my base install, I do not know what library is causing this.  Any help would be appreciated.  I would like to remove the constraint of staying at Dash 2.0.0 as I saw faster response times with Dash 2.1.0.  Thanks!

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `dash/development/update_components.py`
Content:
```
1 import sys
2 import subprocess
3 import shlex
4 import os
5 import argparse
6 import shutil
7 import logging
8 import coloredlogs
9 
10 
11 class _CombinedFormatter(
12     argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter
13 ):
14     pass
15 
16 
17 logger = logging.getLogger(__name__)
18 coloredlogs.install(
19     fmt="%(asctime)s,%(msecs)03d %(levelname)s - %(message)s", datefmt="%H:%M:%S"
20 )
21 
22 
23 def booststrap_components(components_source):
24 
25     is_windows = sys.platform == "win32"
26 
27     source_glob = (
28         components_source
29         if components_source != "all"
30         else "dash-core-components|dash-html-components|dash-table"
31     )
32 
33     cmd = shlex.split(
34         "npx lerna exec --scope *@({})* -- npm i".format(source_glob),
35         posix=not is_windows,
36     )
37 
38     with subprocess.Popen(
39         cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=is_windows
40     ) as proc:
41         out, err = proc.communicate()
42         status = proc.poll()
43 
44     if err:
45         print(err.decode(), file=sys.stderr)
46 
47     if status == 0:
48         print(
49             "🟢 Finished installing npm dependencies for the following component packages: {} (status={}) 🟢".format(
50                 source_glob, status
51             ),
52             file=sys.stderr,
53         )
54     if not out:
55         print(
56             "Failed installing npm dependencies for the following component packages {} (status={})".format(
57                 source_glob, status
58             ),
59             file=sys.stderr,
60         )
61 
62 
63 def build_components(components_source):
64 
65     is_windows = sys.platform == "win32"
66 
67     source_glob = (
68         components_source
69         if components_source != "all"
70         else "dash-core-components|dash-html-components|dash-table"
71     )
72 
73     cmd = shlex.split(
74         "npx lerna exec --scope *@({})* -- npm run build".format(source_glob),
75         posix=not is_windows,
76     )
77 
78     with subprocess.Popen(
79         cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=is_windows
80     ) as proc:
81         out, err = proc.communicate()
82         status = proc.poll()
83 
84     if err:
85         print(err.decode(), file=sys.stderr)
86 
87     if not out:
88         print(
89             "🟢 Finished updating the following component packages {} (status={}) 🟢".format(
90                 source_glob, status
91             ),
92             file=sys.stderr,
93         )
94         sys.exit(1)
95 
96     for package in source_glob.split("|"):
97         build_directory = os.path.join(
98             "components", package, package.replace("-", "_").rstrip("/\\")
99         )
100 
101         dest_dir = (
102             "dcc"
103             if package == "dash-core-components"
104             else "html"
105             if package == "dash-html-components"
106             else "dash_table"
107         )
108 
109         dest_path = os.path.join("dash", dest_dir)
110 
111         if not os.path.exists(dest_path):
112             try:
113                 os.makedirs(dest_path)
114             except OSError:
115                 logger.exception("🚨 Having issues manipulating %s", dest_path)
116                 sys.exit(1)
117 
118         if not os.path.exists(build_directory):
119             print(
120                 "Could not locate build artifacts. Check that the npm build process completed successfully for the given package: {}".format(
121                     package
122                 )
123             )
124         else:
125             print("🚚 Moving build artifacts from " + build_directory + " to Dash 🚚")
126             shutil.rmtree(dest_path)
127             shutil.copytree(build_directory, dest_path)
128             with open(os.path.join(dest_path, ".gitkeep"), "w"):
129                 pass
130             print(
131                 "🟢 Finished moving build artifacts from "
132                 + build_directory
133                 + " to Dash 🟢"
134             )
135 
136 
137 def cli():
138     parser = argparse.ArgumentParser(
139         prog="dash-update-components",
140         formatter_class=_CombinedFormatter,
141         description="Update the specified subcomponent libraries within Dash"
142         " by copying over build artifacts, dependencies, and dependency metadata.",
143     )
144     parser.add_argument(
145         "components_source",
146         help="A glob string that matches the Dash component libraries to be updated (eg.'dash-table' // 'dash-core-components|dash-html-components' // 'all'). The default argument is 'all'.",
147         default="all",
148     )
149 
150     args = parser.parse_args()
151 
152     booststrap_components(args.components_source)
153     build_components(args.components_source)
154 
155 
156 cli()
157
```
--- 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/dash/development/update_components.py b/dash/development/update_components.py
--- a/dash/development/update_components.py
+++ b/dash/development/update_components.py
@@ -42,20 +42,17 @@
         status = proc.poll()
 
     if err:
-        print(err.decode(), file=sys.stderr)
+        print(("🛑 " if status else "") + err.decode(), file=sys.stderr)
 
-    if status == 0:
+    if status or not out:
         print(
-            "🟢 Finished installing npm dependencies for the following component packages: {} (status={}) 🟢".format(
-                source_glob, status
-            ),
+            "🚨 Failed installing npm dependencies for component packages: {source_glob} (status={status}) 🚨",
             file=sys.stderr,
         )
-    if not out:
+        sys.exit(1)
+    else:
         print(
-            "Failed installing npm dependencies for the following component packages {} (status={})".format(
-                source_glob, status
-            ),
+            f"🟢 Finished installing npm dependencies for component packages: {source_glob} 🟢",
             file=sys.stderr,
         )
 
@@ -82,13 +79,11 @@
         status = proc.poll()
 
     if err:
-        print(err.decode(), file=sys.stderr)
+        print(("🛑 " if status else "") + err.decode(), file=sys.stderr)
 
-    if not out:
+    if status or not out:
         print(
-            "🟢 Finished updating the following component packages {} (status={}) 🟢".format(
-                source_glob, status
-            ),
+            f"🚨 Finished updating component packages: {source_glob} (status={status}) 🚨",
             file=sys.stderr,
         )
         sys.exit(1)
@@ -117,21 +112,18 @@
 
         if not os.path.exists(build_directory):
             print(
-                "Could not locate build artifacts. Check that the npm build process completed successfully for the given package: {}".format(
-                    package
-                )
+                "🚨 Could not locate build artifacts."
+                + " Check that the npm build process completed"
+                + f" successfully for package: {package} 🚨"
             )
+            sys.exit(1)
         else:
-            print("🚚 Moving build artifacts from " + build_directory + " to Dash 🚚")
+            print(f"🚚 Moving build artifacts from {build_directory} to Dash 🚚")
             shutil.rmtree(dest_path)
             shutil.copytree(build_directory, dest_path)
             with open(os.path.join(dest_path, ".gitkeep"), "w"):
                 pass
-            print(
-                "🟢 Finished moving build artifacts from "
-                + build_directory
-                + " to Dash 🟢"
-            )
+            print(f"🟢 Finished moving build artifacts from {build_directory} to Dash 🟢")
 
 
 def cli():
@@ -143,7 +135,9 @@
     )
     parser.add_argument(
         "components_source",
-        help="A glob string that matches the Dash component libraries to be updated (eg.'dash-table' // 'dash-core-components|dash-html-components' // 'all'). The default argument is 'all'.",
+        help="A glob string that matches the Dash component libraries to be updated"
+        " (eg.'dash-table' // 'dash-core-components|dash-html-components' // 'all')."
+        " The default argument is 'all'.",
         default="all",
     )
 
@@ -153,4 +147,5 @@
     build_components(args.components_source)
 
 
-cli()
+if __name__ == "__main__":
+    cli()

{"golden_diff": "diff --git a/dash/development/update_components.py b/dash/development/update_components.py\n--- a/dash/development/update_components.py\n+++ b/dash/development/update_components.py\n@@ -42,20 +42,17 @@\n         status = proc.poll()\n \n     if err:\n-        print(err.decode(), file=sys.stderr)\n+        print((\"\ud83d\uded1 \" if status else \"\") + err.decode(), file=sys.stderr)\n \n-    if status == 0:\n+    if status or not out:\n         print(\n-            \"\ud83d\udfe2 Finished installing npm dependencies for the following component packages: {} (status={}) \ud83d\udfe2\".format(\n-                source_glob, status\n-            ),\n+            \"\ud83d\udea8 Failed installing npm dependencies for component packages: {source_glob} (status={status}) \ud83d\udea8\",\n             file=sys.stderr,\n         )\n-    if not out:\n+        sys.exit(1)\n+    else:\n         print(\n-            \"Failed installing npm dependencies for the following component packages {} (status={})\".format(\n-                source_glob, status\n-            ),\n+            f\"\ud83d\udfe2 Finished installing npm dependencies for component packages: {source_glob} \ud83d\udfe2\",\n             file=sys.stderr,\n         )\n \n@@ -82,13 +79,11 @@\n         status = proc.poll()\n \n     if err:\n-        print(err.decode(), file=sys.stderr)\n+        print((\"\ud83d\uded1 \" if status else \"\") + err.decode(), file=sys.stderr)\n \n-    if not out:\n+    if status or not out:\n         print(\n-            \"\ud83d\udfe2 Finished updating the following component packages {} (status={}) \ud83d\udfe2\".format(\n-                source_glob, status\n-            ),\n+            f\"\ud83d\udea8 Finished updating component packages: {source_glob} (status={status}) \ud83d\udea8\",\n             file=sys.stderr,\n         )\n         sys.exit(1)\n@@ -117,21 +112,18 @@\n \n         if not os.path.exists(build_directory):\n             print(\n-                \"Could not locate build artifacts. Check that the npm build process completed successfully for the given package: {}\".format(\n-                    package\n-                )\n+                \"\ud83d\udea8 Could not locate build artifacts.\"\n+                + \" Check that the npm build process completed\"\n+                + f\" successfully for package: {package} \ud83d\udea8\"\n             )\n+            sys.exit(1)\n         else:\n-            print(\"\ud83d\ude9a Moving build artifacts from \" + build_directory + \" to Dash \ud83d\ude9a\")\n+            print(f\"\ud83d\ude9a Moving build artifacts from {build_directory} to Dash \ud83d\ude9a\")\n             shutil.rmtree(dest_path)\n             shutil.copytree(build_directory, dest_path)\n             with open(os.path.join(dest_path, \".gitkeep\"), \"w\"):\n                 pass\n-            print(\n-                \"\ud83d\udfe2 Finished moving build artifacts from \"\n-                + build_directory\n-                + \" to Dash \ud83d\udfe2\"\n-            )\n+            print(f\"\ud83d\udfe2 Finished moving build artifacts from {build_directory} to Dash \ud83d\udfe2\")\n \n \n def cli():\n@@ -143,7 +135,9 @@\n     )\n     parser.add_argument(\n         \"components_source\",\n-        help=\"A glob string that matches the Dash component libraries to be updated (eg.'dash-table' // 'dash-core-components|dash-html-components' // 'all'). The default argument is 'all'.\",\n+        help=\"A glob string that matches the Dash component libraries to be updated\"\n+        \" (eg.'dash-table' // 'dash-core-components|dash-html-components' // 'all').\"\n+        \" The default argument is 'all'.\",\n         default=\"all\",\n     )\n \n@@ -153,4 +147,5 @@\n     build_components(args.components_source)\n \n \n-cli()\n+if __name__ == \"__main__\":\n+    cli()\n", "issue": "Remove `webdriver-manager` from `dash[testing]` requirements\nThis was added in #1801 but wasn't really clear why it was needed, and it reaches out to the internet during its installation (even if installed from a local PyPI mirror) which causes problems for some users.\n[BUG] Dash DataTable style_header text_alignment breaks between Dash v2.0.0 and v2.1.0\nProduction environment is under a customer container hosting environment that hosts docker container in a large corporate environment.  Docker container is setup with rhel 7 (Redhat) with an Apache 2.4 web server.  Python 3.6 is the version of python using pip as the installation for packages.\r\n\r\n-  replace the result of `pip list | grep dash` below\r\n```\r\ndash                       2.1.0    \r\ndash-bootstrap-components  1.0.2    \r\ndash-core-components       2.0.0    \r\ndash-html-components       2.0.0    \r\ndash-renderer              1.9.1    \r\ndash-table                 5.0.0\r\n```\r\n\r\n-  if frontend related, tell us your Browser, Version and OS\r\n\r\n    - OS: MacOS Monterey version 12.2\r\n    - Browser Chrome\r\n    - Version 98.0.4758.80\r\n\r\n**Describe the bug**\r\n\r\nWhen using 'text-align': 'center' in the style_header directive within the dash_table.DataTable, under Dash 2.1.0, the headings for the table are not centered, rather they are right aligned, regardless of the setting of the 'text-align' value.  In fact, directly editing the text-align within Chrome's developer tool will not change the alignment.  Changing other attributes (font, color, etc... will work).  \r\n\r\n**Expected behavior**\r\n\r\nI would expect that when 'text-align': 'center' is specified for the style_header directive within dash_table.DataTable that the headings for the columns specified would be centered above the column.\r\n\r\n**Screenshots**\r\n\r\n![image](https://user-images.githubusercontent.com/3968562/152881625-b91b2ad5-317c-4ae6-ba90-3e289fcea525.png)\r\n\r\n**Additional Information**\r\nI've been able to workaround this issue by reverting to Dash 2.0.0 in my production build, but I have not been able to build a similar working environment, neither in pip nor conda.  My production version is working.  I only reverted to Dash 2.0.0 since it was a very recent release, and then the behavior of the dash_table.DataTable worked correctly.  It was the only change I made to the Docker build.  Now, regardless of whether I use Dash 2.0.0 or Dash 2.1.0, I'm seeing the persistent right alignment of headers in my DataTables.  \r\n\r\nI do not know if it will help, but here is an example of code that I saw work under Dash 2.0.0, and then fail once I upgraded to Dash 2.1.0:\r\n```\r\nimport pandas as pd\r\nfrom dash import dcc\r\n# import dash_core_components as dcc\r\nfrom dash import html\r\n# import dash_html_components as html\r\nimport dash_bootstrap_components as dbc\r\nfrom dash.dependencies import Input, Output\r\nimport plotly.express as px\r\nimport time\r\nimport random\r\n\r\napp = dash.Dash(__name__)\r\n\r\ndef get_rand_data():\r\n    mylist=[random.randint(1,6) for _ in range(6)]\r\n    return mylist\r\n\r\ndef build_data(mylist):\r\n    df = pd.DataFrame({\r\n        \"Fruit\": [\"Apples\", \"Oranges\", \"Bananas\", \"Apples\", \"Oranges\", \"Bananas\"],\r\n        \"Amount\": mylist,\r\n        \"City\": [\"SF\", \"SF\", \"SF\", \"Montreal\", \"Montreal\", \"Montreal\"]\r\n    })\r\n    dcc.Store(id='new_data', data=df.to_json())\r\n    return df\r\n\r\ndef draw_graph(df):\r\n    fig = px.bar(df, x=\"Fruit\", y=\"Amount\", color=\"City\", barmode=\"group\")\r\n    return fig\r\n\r\ndef get_table():\r\n    data_table =  dash_table.DataTable(\r\n        columns=[\r\n            {\"name\": [\"\", \"Year\"], \"id\": \"year\"},\r\n            {\"name\": [\"City\", \"Montreal\"], \"id\": \"montreal\"},\r\n            {\"name\": [\"City\", \"Toronto\"], \"id\": \"toronto\"},\r\n            {\"name\": [\"City\", \"Ottawa\"], \"id\": \"ottawa\"},\r\n            {\"name\": [\"City\", \"Vancouver\"], \"id\": \"vancouver\"},\r\n            {\"name\": [\"Climate\", \"Temperature\"], \"id\": \"temp\"},\r\n            {\"name\": [\"Climate\", \"Humidity\"], \"id\": \"humidity\"},\r\n        ],\r\n        data=[\r\n            {\r\n                \"year\": i,\r\n                \"montreal\": i * 10,\r\n                \"toronto\": i * 100,\r\n                \"ottawa\": i * -1,\r\n                \"vancouver\": i * -10,\r\n                \"temp\": i * -100,\r\n                \"humidity\": i * 5,\r\n            }\r\n            for i in range(10)\r\n        ],\r\n        style_header={\r\n                'text-align': 'center',\r\n            },\r\n        merge_duplicate_headers=True,\r\n    )\r\n    return data_table\r\n\r\n\r\nmylist=get_rand_data()\r\ndf = build_data(mylist)\r\nfig = draw_graph(df)\r\ndata_table = get_table()\r\n\r\nrefresh_button = dbc.Button('Refresh Data', color=\"info\", className=\"me-1\", id='refresh_button_lmd')\r\n\r\napp.layout = html.Div(children=[\r\n    html.H1(children='Hello Dash'),\r\n    refresh_button,\r\n    html.Div(children=[\r\n        data_table\r\n    ]),\r\n    dcc.Store(id='new_data'),\r\n    dcc.Loading(\r\n        id='loading-data',\r\n        children=[\r\n            html.Div(children=[\r\n                dcc.Graph(\r\n                    id='example-graph',\r\n                    figure=fig\r\n                )\r\n            ]\r\n            )\r\n        ],\r\n        type='circle',\r\n    ),\r\n])\r\n\r\n\r\n@app.callback(Output(\"example-graph\", \"figure\"),\r\n              Input(\"new_data\", \"data\"))\r\ndef on_data(data):\r\n    df = pd.read_json(data)\r\n    time.sleep(5)\r\n    fig = draw_graph(df)\r\n    return fig\r\n\r\n\r\n@app.callback(Output('new_data', 'data'),\r\n              Input('refresh_button_lmd', 'n_clicks'))\r\ndef new_data(n_clicks):\r\n    if n_clicks is None:\r\n        print(\"Override Startup\")\r\n        mylist = get_rand_data()\r\n        df = build_data(mylist)\r\n        data = df.to_json()\r\n    else:\r\n        print(f'Button was clicked, this is {n_clicks} times.')\r\n        mylist = get_rand_data()\r\n        df = build_data(mylist)\r\n        data=df.to_json()\r\n    return data\r\n\r\nif __name__ == '__main__':\r\n    app.run_server(debug=True)\r\n```\r\n\r\nI suspect that perhaps an upgrade supporting the move to Dash 2.1.0 might be the issue, and that now that I've moved my base install, I do not know what library is causing this.  Any help would be appreciated.  I would like to remove the constraint of staying at Dash 2.0.0 as I saw faster response times with Dash 2.1.0.  Thanks!\n", "before_files": [{"content": "import sys\nimport subprocess\nimport shlex\nimport os\nimport argparse\nimport shutil\nimport logging\nimport coloredlogs\n\n\nclass _CombinedFormatter(\n    argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter\n):\n    pass\n\n\nlogger = logging.getLogger(__name__)\ncoloredlogs.install(\n    fmt=\"%(asctime)s,%(msecs)03d %(levelname)s - %(message)s\", datefmt=\"%H:%M:%S\"\n)\n\n\ndef booststrap_components(components_source):\n\n    is_windows = sys.platform == \"win32\"\n\n    source_glob = (\n        components_source\n        if components_source != \"all\"\n        else \"dash-core-components|dash-html-components|dash-table\"\n    )\n\n    cmd = shlex.split(\n        \"npx lerna exec --scope *@({})* -- npm i\".format(source_glob),\n        posix=not is_windows,\n    )\n\n    with subprocess.Popen(\n        cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=is_windows\n    ) as proc:\n        out, err = proc.communicate()\n        status = proc.poll()\n\n    if err:\n        print(err.decode(), file=sys.stderr)\n\n    if status == 0:\n        print(\n            \"\ud83d\udfe2 Finished installing npm dependencies for the following component packages: {} (status={}) \ud83d\udfe2\".format(\n                source_glob, status\n            ),\n            file=sys.stderr,\n        )\n    if not out:\n        print(\n            \"Failed installing npm dependencies for the following component packages {} (status={})\".format(\n                source_glob, status\n            ),\n            file=sys.stderr,\n        )\n\n\ndef build_components(components_source):\n\n    is_windows = sys.platform == \"win32\"\n\n    source_glob = (\n        components_source\n        if components_source != \"all\"\n        else \"dash-core-components|dash-html-components|dash-table\"\n    )\n\n    cmd = shlex.split(\n        \"npx lerna exec --scope *@({})* -- npm run build\".format(source_glob),\n        posix=not is_windows,\n    )\n\n    with subprocess.Popen(\n        cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=is_windows\n    ) as proc:\n        out, err = proc.communicate()\n        status = proc.poll()\n\n    if err:\n        print(err.decode(), file=sys.stderr)\n\n    if not out:\n        print(\n            \"\ud83d\udfe2 Finished updating the following component packages {} (status={}) \ud83d\udfe2\".format(\n                source_glob, status\n            ),\n            file=sys.stderr,\n        )\n        sys.exit(1)\n\n    for package in source_glob.split(\"|\"):\n        build_directory = os.path.join(\n            \"components\", package, package.replace(\"-\", \"_\").rstrip(\"/\\\\\")\n        )\n\n        dest_dir = (\n            \"dcc\"\n            if package == \"dash-core-components\"\n            else \"html\"\n            if package == \"dash-html-components\"\n            else \"dash_table\"\n        )\n\n        dest_path = os.path.join(\"dash\", dest_dir)\n\n        if not os.path.exists(dest_path):\n            try:\n                os.makedirs(dest_path)\n            except OSError:\n                logger.exception(\"\ud83d\udea8 Having issues manipulating %s\", dest_path)\n                sys.exit(1)\n\n        if not os.path.exists(build_directory):\n            print(\n                \"Could not locate build artifacts. Check that the npm build process completed successfully for the given package: {}\".format(\n                    package\n                )\n            )\n        else:\n            print(\"\ud83d\ude9a Moving build artifacts from \" + build_directory + \" to Dash \ud83d\ude9a\")\n            shutil.rmtree(dest_path)\n            shutil.copytree(build_directory, dest_path)\n            with open(os.path.join(dest_path, \".gitkeep\"), \"w\"):\n                pass\n            print(\n                \"\ud83d\udfe2 Finished moving build artifacts from \"\n                + build_directory\n                + \" to Dash \ud83d\udfe2\"\n            )\n\n\ndef cli():\n    parser = argparse.ArgumentParser(\n        prog=\"dash-update-components\",\n        formatter_class=_CombinedFormatter,\n        description=\"Update the specified subcomponent libraries within Dash\"\n        \" by copying over build artifacts, dependencies, and dependency metadata.\",\n    )\n    parser.add_argument(\n        \"components_source\",\n        help=\"A glob string that matches the Dash component libraries to be updated (eg.'dash-table' // 'dash-core-components|dash-html-components' // 'all'). The default argument is 'all'.\",\n        default=\"all\",\n    )\n\n    args = parser.parse_args()\n\n    booststrap_components(args.components_source)\n    build_components(args.components_source)\n\n\ncli()\n", "path": "dash/development/update_components.py"}], "after_files": [{"content": "import sys\nimport subprocess\nimport shlex\nimport os\nimport argparse\nimport shutil\nimport logging\nimport coloredlogs\n\n\nclass _CombinedFormatter(\n    argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter\n):\n    pass\n\n\nlogger = logging.getLogger(__name__)\ncoloredlogs.install(\n    fmt=\"%(asctime)s,%(msecs)03d %(levelname)s - %(message)s\", datefmt=\"%H:%M:%S\"\n)\n\n\ndef booststrap_components(components_source):\n\n    is_windows = sys.platform == \"win32\"\n\n    source_glob = (\n        components_source\n        if components_source != \"all\"\n        else \"dash-core-components|dash-html-components|dash-table\"\n    )\n\n    cmd = shlex.split(\n        \"npx lerna exec --scope *@({})* -- npm i\".format(source_glob),\n        posix=not is_windows,\n    )\n\n    with subprocess.Popen(\n        cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=is_windows\n    ) as proc:\n        out, err = proc.communicate()\n        status = proc.poll()\n\n    if err:\n        print((\"\ud83d\uded1 \" if status else \"\") + err.decode(), file=sys.stderr)\n\n    if status or not out:\n        print(\n            \"\ud83d\udea8 Failed installing npm dependencies for component packages: {source_glob} (status={status}) \ud83d\udea8\",\n            file=sys.stderr,\n        )\n        sys.exit(1)\n    else:\n        print(\n            f\"\ud83d\udfe2 Finished installing npm dependencies for component packages: {source_glob} \ud83d\udfe2\",\n            file=sys.stderr,\n        )\n\n\ndef build_components(components_source):\n\n    is_windows = sys.platform == \"win32\"\n\n    source_glob = (\n        components_source\n        if components_source != \"all\"\n        else \"dash-core-components|dash-html-components|dash-table\"\n    )\n\n    cmd = shlex.split(\n        \"npx lerna exec --scope *@({})* -- npm run build\".format(source_glob),\n        posix=not is_windows,\n    )\n\n    with subprocess.Popen(\n        cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=is_windows\n    ) as proc:\n        out, err = proc.communicate()\n        status = proc.poll()\n\n    if err:\n        print((\"\ud83d\uded1 \" if status else \"\") + err.decode(), file=sys.stderr)\n\n    if status or not out:\n        print(\n            f\"\ud83d\udea8 Finished updating component packages: {source_glob} (status={status}) \ud83d\udea8\",\n            file=sys.stderr,\n        )\n        sys.exit(1)\n\n    for package in source_glob.split(\"|\"):\n        build_directory = os.path.join(\n            \"components\", package, package.replace(\"-\", \"_\").rstrip(\"/\\\\\")\n        )\n\n        dest_dir = (\n            \"dcc\"\n            if package == \"dash-core-components\"\n            else \"html\"\n            if package == \"dash-html-components\"\n            else \"dash_table\"\n        )\n\n        dest_path = os.path.join(\"dash\", dest_dir)\n\n        if not os.path.exists(dest_path):\n            try:\n                os.makedirs(dest_path)\n            except OSError:\n                logger.exception(\"\ud83d\udea8 Having issues manipulating %s\", dest_path)\n                sys.exit(1)\n\n        if not os.path.exists(build_directory):\n            print(\n                \"\ud83d\udea8 Could not locate build artifacts.\"\n                + \" Check that the npm build process completed\"\n                + f\" successfully for package: {package} \ud83d\udea8\"\n            )\n            sys.exit(1)\n        else:\n            print(f\"\ud83d\ude9a Moving build artifacts from {build_directory} to Dash \ud83d\ude9a\")\n            shutil.rmtree(dest_path)\n            shutil.copytree(build_directory, dest_path)\n            with open(os.path.join(dest_path, \".gitkeep\"), \"w\"):\n                pass\n            print(f\"\ud83d\udfe2 Finished moving build artifacts from {build_directory} to Dash \ud83d\udfe2\")\n\n\ndef cli():\n    parser = argparse.ArgumentParser(\n        prog=\"dash-update-components\",\n        formatter_class=_CombinedFormatter,\n        description=\"Update the specified subcomponent libraries within Dash\"\n        \" by copying over build artifacts, dependencies, and dependency metadata.\",\n    )\n    parser.add_argument(\n        \"components_source\",\n        help=\"A glob string that matches the Dash component libraries to be updated\"\n        \" (eg.'dash-table' // 'dash-core-components|dash-html-components' // 'all').\"\n        \" The default argument is 'all'.\",\n        default=\"all\",\n    )\n\n    args = parser.parse_args()\n\n    booststrap_components(args.components_source)\n    build_components(args.components_source)\n\n\nif __name__ == \"__main__\":\n    cli()\n", "path": "dash/development/update_components.py"}]}