We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Setup CI workflow to build and upload galleries
Although we have logic to download pre-built galleries in the documentation

https://github.com/pystiche/pystiche/blob/65f4d787e44b1ffbf7e5b6e48298ed8c7460e5a9/docs/source/conf.py#L160-L166

the builder isn't running for quite some time, because I have no longer have access to the infrastructure.

Preferably, we should have a CI workflow that does this. The problem is, that without a GPU our gallery takes forever to build. Since CI machines that have a GPU are not free (at least I couldn't find any), we probably need to spend some money to achieve this. 

So far I came up with two possible solutions:

1. Build our own custom build server with a GPU and run a self-hosted GitHub Actions workflow on it. This is problematic for a couple of reasons:
    1. GitHub actually warns not to do that in public repositories due to security concerns.
    2. Buying the machine and especially the GPU is quite expensive and as long no one sponsors this, I'm currently not willing to do this out of my own pocket.
    3. We need to maintain the server which will take some time from doing something else on `pystiche`.
2. Spin up a cloud instance with GPU to do the building for us. This solves all the issues of 1. with the disadvantage of being harder to setup. But this also vanishes if we use something like [`cirun.io`](https://cirun.io) (cc @aktech). It looks like other than specifying the type of cloud instance we want to use we can simply use the default GitHub Actions workflow syntax, which is amazing.

The only roadblock I'm currently seeing is that we probably don't need a run every day. If you look at the past commit history, there are quite a few days were no commit is merged so we would be wasting money by running the build every day. My current idea is to run a default CPU workflow that checks if the current commit was already built and only if that is not the case spins up the could instance. From a quick research into this, we probably can use https://github.com/peter-evans/repository-dispatch is a dispatcher.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `docs/source/conf.py`
Content:
```
1 import contextlib
2 import os
3 import re
4 import shutil
5 import warnings
6 from datetime import datetime
7 from distutils.util import strtobool
8 from importlib_metadata import metadata as extract_metadata
9 from os import path
10 from unittest import mock
11 from urllib.parse import urljoin
12 
13 from sphinx_gallery.sorting import ExampleTitleSortKey, ExplicitOrder
14 from tqdm import tqdm
15 
16 import torch
17 
18 from pystiche.misc import download_file
19 
20 HERE = path.dirname(__file__)
21 PROJECT_ROOT = path.abspath(path.join(HERE, "..", ".."))
22 
23 
24 def get_bool_env_var(name, default=False):
25     try:
26         return bool(strtobool(os.environ[name]))
27     except KeyError:
28         return default
29 
30 
31 GITHUB_ACTIONS = get_bool_env_var("GITHUB_ACTIONS")
32 RTD = get_bool_env_var("READTHEDOCS")
33 CI = GITHUB_ACTIONS or RTD or get_bool_env_var("CI")
34 
35 
36 def project():
37     extension = None
38 
39     metadata = extract_metadata("pystiche")
40     project = metadata["name"]
41     author = metadata["author"]
42     copyright = f"{datetime.now().year}, {author}"
43     release = metadata["version"]
44     version = release.split(".dev")[0]
45     config = dict(
46         project=project,
47         author=author,
48         copyright=copyright,
49         release=release,
50         version=version,
51     )
52 
53     return extension, config
54 
55 
56 def autodoc():
57     extensions = [
58         "sphinx.ext.autodoc",
59         "sphinx.ext.napoleon",
60         "sphinx_autodoc_typehints",
61     ]
62 
63     config = None
64 
65     return extensions, config
66 
67 
68 def intersphinx():
69     extension = "sphinx.ext.intersphinx"
70     config = dict(
71         intersphinx_mapping={
72             "python": ("https://docs.python.org/3.6", None),
73             "torch": ("https://pytorch.org/docs/stable/", None),
74             "torchvision": ("https://pytorch.org/docs/stable/", None),
75             "PIL": ("https://pillow.readthedocs.io/en/stable/", None),
76             "numpy": ("https://numpy.org/doc/1.18/", None),
77             "requests": ("https://requests.readthedocs.io/en/stable/", None),
78             "matplotlib": ("https://matplotlib.org", None),
79         }
80     )
81     return extension, config
82 
83 
84 def html():
85     extension = None
86 
87     config = dict(html_theme="sphinx_rtd_theme")
88 
89     return extension, config
90 
91 
92 def latex():
93     extension = None
94 
95     with open(path.join(HERE, "custom_cmds.tex"), "r") as fh:
96         custom_cmds = fh.read()
97     config = dict(
98         latex_elements={"preamble": custom_cmds},
99         mathjax_inline=[r"\(" + custom_cmds, r"\)"],
100         mathjax_display=[r"\[" + custom_cmds, r"\]"],
101     )
102 
103     return extension, config
104 
105 
106 def bibtex():
107     extension = "sphinxcontrib.bibtex"
108 
109     config = dict(bibtex_bibfiles=["references.bib"])
110 
111     return extension, config
112 
113 
114 def doctest():
115     extension = "sphinx.ext.doctest"
116 
117     doctest_global_setup = """
118 import torch
119 from torch import nn
120 
121 import pystiche
122 
123 import warnings
124 warnings.filterwarnings("ignore", category=FutureWarning)
125 
126 from unittest import mock
127 
128 patcher = mock.patch(
129     "pystiche.enc.models.utils.ModelMultiLayerEncoder.load_state_dict_from_url"
130 )
131 patcher.start()
132 """
133 
134     doctest_global_cleanup = """
135 mock.patch.stopall()
136 """
137     config = dict(
138         doctest_global_setup=doctest_global_setup,
139         doctest_global_cleanup=doctest_global_cleanup,
140     )
141 
142     return extension, config
143 
144 
145 def sphinx_gallery():
146     extension = "sphinx_gallery.gen_gallery"
147 
148     plot_gallery = get_bool_env_var("PYSTICHE_PLOT_GALLERY", default=not CI)
149     download_gallery = get_bool_env_var("PYSTICHE_DOWNLOAD_GALLERY", default=CI)
150 
151     def download():
152         nonlocal extension
153         nonlocal plot_gallery
154 
155         # version and release are available as soon as the project config is loaded
156         version = globals()["version"]
157         release = globals()["release"]
158 
159         base = "https://download.pystiche.org/galleries/"
160         is_dev = version != release
161         file = "master.zip" if is_dev else f"v{version}.zip"
162 
163         url = urljoin(base, file)
164         print(f"Downloading pre-built galleries from {url}")
165         download_file(url, file)
166 
167         with contextlib.suppress(FileNotFoundError):
168             shutil.rmtree(path.join(HERE, "galleries"))
169         shutil.unpack_archive(file, extract_dir=".")
170         os.remove(file)
171 
172         extension = "sphinx_gallery.load_style"
173         plot_gallery = False
174 
175     def show_cuda_memory(func):
176         torch.cuda.reset_peak_memory_stats()
177         out = func()
178 
179         stats = torch.cuda.memory_stats()
180         peak_bytes_usage = stats["allocated_bytes.all.peak"]
181         memory = peak_bytes_usage / 1024 ** 2
182 
183         return memory, out
184 
185     def patch_tqdm():
186         patchers = [mock.patch("tqdm.std._supports_unicode", return_value=True)]
187 
188         display = tqdm.display
189         close = tqdm.close
190         displayed = set()
191 
192         def display_only_last(self, msg=None, pos=None):
193             if self.n != self.total or self in displayed:
194                 return
195 
196             display(self, msg=msg, pos=pos)
197             displayed.add(self)
198 
199         patchers.append(mock.patch("tqdm.std.tqdm.display", new=display_only_last))
200 
201         def close_(self):
202             close(self)
203             with contextlib.suppress(KeyError):
204                 displayed.remove(self)
205 
206         patchers.append(mock.patch("tqdm.std.tqdm.close", new=close_))
207 
208         for patcher in patchers:
209             patcher.start()
210 
211     class PysticheExampleTitleSortKey(ExampleTitleSortKey):
212         def __call__(self, filename):
213             # The beginner example *without* pystiche is placed before the example
214             # *with* to clarify the narrative.
215             if filename == "example_nst_without_pystiche.py":
216                 return "1"
217             elif filename == "example_nst_with_pystiche.py":
218                 return "2"
219             else:
220                 return super().__call__(filename)
221 
222     def filter_warnings():
223         # See #https://github.com/pytorch/pytorch/issues/60053
224         warnings.filterwarnings(
225             "ignore",
226             category=UserWarning,
227             message=(
228                 re.escape(
229                     "Named tensors and all their associated APIs are an experimental "
230                     "feature and subject to change. Please do not use them for "
231                     "anything important until they are released as stable. (Triggered "
232                     "internally at  /pytorch/c10/core/TensorImpl.h:1156.)"
233                 )
234             ),
235         )
236 
237     if download_gallery:
238         download()
239 
240     if plot_gallery and not torch.cuda.is_available():
241         msg = (
242             "The galleries will be built, but CUDA is not available. "
243             "This will take a long time."
244         )
245         print(msg)
246 
247     sphinx_gallery_conf = {
248         "examples_dirs": path.join(PROJECT_ROOT, "examples"),
249         "gallery_dirs": path.join("galleries", "examples"),
250         "filename_pattern": re.escape(os.sep) + r"example_\w+[.]py$",
251         "ignore_pattern": re.escape(os.sep) + r"_\w+[.]py$",
252         "line_numbers": True,
253         "remove_config_comments": True,
254         "plot_gallery": plot_gallery,
255         "subsection_order": ExplicitOrder(
256             [
257                 path.join("..", "..", "examples", sub_gallery)
258                 for sub_gallery in ("beginner", "advanced")
259             ]
260         ),
261         "within_subsection_order": PysticheExampleTitleSortKey,
262         "show_memory": show_cuda_memory if torch.cuda.is_available() else True,
263     }
264 
265     config = dict(sphinx_gallery_conf=sphinx_gallery_conf)
266     filter_warnings()
267 
268     patch_tqdm()
269     filter_warnings()
270 
271     return extension, config
272 
273 
274 def logo():
275     extension = None
276 
277     config = dict(html_logo="../../logo.svg")
278 
279     return extension, config
280 
281 
282 extensions = []
283 for loader in (
284     project,
285     autodoc,
286     intersphinx,
287     html,
288     latex,
289     bibtex,
290     doctest,
291     sphinx_gallery,
292     logo,
293 ):
294     extension, config = loader()
295 
296     if extension:
297         if isinstance(extension, str):
298             extension = (extension,)
299         extensions.extend(extension)
300 
301     if config:
302         globals().update(config)
303
```
--- 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/docs/source/conf.py b/docs/source/conf.py
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -158,7 +158,7 @@
 
         base = "https://download.pystiche.org/galleries/"
         is_dev = version != release
-        file = "master.zip" if is_dev else f"v{version}.zip"
+        file = "main.zip" if is_dev else f"v{version}.zip"
 
         url = urljoin(base, file)
         print(f"Downloading pre-built galleries from {url}")

{"golden_diff": "diff --git a/docs/source/conf.py b/docs/source/conf.py\n--- a/docs/source/conf.py\n+++ b/docs/source/conf.py\n@@ -158,7 +158,7 @@\n \n         base = \"https://download.pystiche.org/galleries/\"\n         is_dev = version != release\n-        file = \"master.zip\" if is_dev else f\"v{version}.zip\"\n+        file = \"main.zip\" if is_dev else f\"v{version}.zip\"\n \n         url = urljoin(base, file)\n         print(f\"Downloading pre-built galleries from {url}\")\n", "issue": "Setup CI workflow to build and upload galleries\nAlthough we have logic to download pre-built galleries in the documentation\r\n\r\nhttps://github.com/pystiche/pystiche/blob/65f4d787e44b1ffbf7e5b6e48298ed8c7460e5a9/docs/source/conf.py#L160-L166\r\n\r\nthe builder isn't running for quite some time, because I have no longer have access to the infrastructure.\r\n\r\nPreferably, we should have a CI workflow that does this. The problem is, that without a GPU our gallery takes forever to build. Since CI machines that have a GPU are not free (at least I couldn't find any), we probably need to spend some money to achieve this. \r\n\r\nSo far I came up with two possible solutions:\r\n\r\n1. Build our own custom build server with a GPU and run a self-hosted GitHub Actions workflow on it. This is problematic for a couple of reasons:\r\n    1. GitHub actually warns not to do that in public repositories due to security concerns.\r\n    2. Buying the machine and especially the GPU is quite expensive and as long no one sponsors this, I'm currently not willing to do this out of my own pocket.\r\n    3. We need to maintain the server which will take some time from doing something else on `pystiche`.\r\n2. Spin up a cloud instance with GPU to do the building for us. This solves all the issues of 1. with the disadvantage of being harder to setup. But this also vanishes if we use something like [`cirun.io`](https://cirun.io) (cc @aktech). It looks like other than specifying the type of cloud instance we want to use we can simply use the default GitHub Actions workflow syntax, which is amazing.\r\n\r\nThe only roadblock I'm currently seeing is that we probably don't need a run every day. If you look at the past commit history, there are quite a few days were no commit is merged so we would be wasting money by running the build every day. My current idea is to run a default CPU workflow that checks if the current commit was already built and only if that is not the case spins up the could instance. From a quick research into this, we probably can use https://github.com/peter-evans/repository-dispatch is a dispatcher.\r\n\n", "before_files": [{"content": "import contextlib\nimport os\nimport re\nimport shutil\nimport warnings\nfrom datetime import datetime\nfrom distutils.util import strtobool\nfrom importlib_metadata import metadata as extract_metadata\nfrom os import path\nfrom unittest import mock\nfrom urllib.parse import urljoin\n\nfrom sphinx_gallery.sorting import ExampleTitleSortKey, ExplicitOrder\nfrom tqdm import tqdm\n\nimport torch\n\nfrom pystiche.misc import download_file\n\nHERE = path.dirname(__file__)\nPROJECT_ROOT = path.abspath(path.join(HERE, \"..\", \"..\"))\n\n\ndef get_bool_env_var(name, default=False):\n    try:\n        return bool(strtobool(os.environ[name]))\n    except KeyError:\n        return default\n\n\nGITHUB_ACTIONS = get_bool_env_var(\"GITHUB_ACTIONS\")\nRTD = get_bool_env_var(\"READTHEDOCS\")\nCI = GITHUB_ACTIONS or RTD or get_bool_env_var(\"CI\")\n\n\ndef project():\n    extension = None\n\n    metadata = extract_metadata(\"pystiche\")\n    project = metadata[\"name\"]\n    author = metadata[\"author\"]\n    copyright = f\"{datetime.now().year}, {author}\"\n    release = metadata[\"version\"]\n    version = release.split(\".dev\")[0]\n    config = dict(\n        project=project,\n        author=author,\n        copyright=copyright,\n        release=release,\n        version=version,\n    )\n\n    return extension, config\n\n\ndef autodoc():\n    extensions = [\n        \"sphinx.ext.autodoc\",\n        \"sphinx.ext.napoleon\",\n        \"sphinx_autodoc_typehints\",\n    ]\n\n    config = None\n\n    return extensions, config\n\n\ndef intersphinx():\n    extension = \"sphinx.ext.intersphinx\"\n    config = dict(\n        intersphinx_mapping={\n            \"python\": (\"https://docs.python.org/3.6\", None),\n            \"torch\": (\"https://pytorch.org/docs/stable/\", None),\n            \"torchvision\": (\"https://pytorch.org/docs/stable/\", None),\n            \"PIL\": (\"https://pillow.readthedocs.io/en/stable/\", None),\n            \"numpy\": (\"https://numpy.org/doc/1.18/\", None),\n            \"requests\": (\"https://requests.readthedocs.io/en/stable/\", None),\n            \"matplotlib\": (\"https://matplotlib.org\", None),\n        }\n    )\n    return extension, config\n\n\ndef html():\n    extension = None\n\n    config = dict(html_theme=\"sphinx_rtd_theme\")\n\n    return extension, config\n\n\ndef latex():\n    extension = None\n\n    with open(path.join(HERE, \"custom_cmds.tex\"), \"r\") as fh:\n        custom_cmds = fh.read()\n    config = dict(\n        latex_elements={\"preamble\": custom_cmds},\n        mathjax_inline=[r\"\\(\" + custom_cmds, r\"\\)\"],\n        mathjax_display=[r\"\\[\" + custom_cmds, r\"\\]\"],\n    )\n\n    return extension, config\n\n\ndef bibtex():\n    extension = \"sphinxcontrib.bibtex\"\n\n    config = dict(bibtex_bibfiles=[\"references.bib\"])\n\n    return extension, config\n\n\ndef doctest():\n    extension = \"sphinx.ext.doctest\"\n\n    doctest_global_setup = \"\"\"\nimport torch\nfrom torch import nn\n\nimport pystiche\n\nimport warnings\nwarnings.filterwarnings(\"ignore\", category=FutureWarning)\n\nfrom unittest import mock\n\npatcher = mock.patch(\n    \"pystiche.enc.models.utils.ModelMultiLayerEncoder.load_state_dict_from_url\"\n)\npatcher.start()\n\"\"\"\n\n    doctest_global_cleanup = \"\"\"\nmock.patch.stopall()\n\"\"\"\n    config = dict(\n        doctest_global_setup=doctest_global_setup,\n        doctest_global_cleanup=doctest_global_cleanup,\n    )\n\n    return extension, config\n\n\ndef sphinx_gallery():\n    extension = \"sphinx_gallery.gen_gallery\"\n\n    plot_gallery = get_bool_env_var(\"PYSTICHE_PLOT_GALLERY\", default=not CI)\n    download_gallery = get_bool_env_var(\"PYSTICHE_DOWNLOAD_GALLERY\", default=CI)\n\n    def download():\n        nonlocal extension\n        nonlocal plot_gallery\n\n        # version and release are available as soon as the project config is loaded\n        version = globals()[\"version\"]\n        release = globals()[\"release\"]\n\n        base = \"https://download.pystiche.org/galleries/\"\n        is_dev = version != release\n        file = \"master.zip\" if is_dev else f\"v{version}.zip\"\n\n        url = urljoin(base, file)\n        print(f\"Downloading pre-built galleries from {url}\")\n        download_file(url, file)\n\n        with contextlib.suppress(FileNotFoundError):\n            shutil.rmtree(path.join(HERE, \"galleries\"))\n        shutil.unpack_archive(file, extract_dir=\".\")\n        os.remove(file)\n\n        extension = \"sphinx_gallery.load_style\"\n        plot_gallery = False\n\n    def show_cuda_memory(func):\n        torch.cuda.reset_peak_memory_stats()\n        out = func()\n\n        stats = torch.cuda.memory_stats()\n        peak_bytes_usage = stats[\"allocated_bytes.all.peak\"]\n        memory = peak_bytes_usage / 1024 ** 2\n\n        return memory, out\n\n    def patch_tqdm():\n        patchers = [mock.patch(\"tqdm.std._supports_unicode\", return_value=True)]\n\n        display = tqdm.display\n        close = tqdm.close\n        displayed = set()\n\n        def display_only_last(self, msg=None, pos=None):\n            if self.n != self.total or self in displayed:\n                return\n\n            display(self, msg=msg, pos=pos)\n            displayed.add(self)\n\n        patchers.append(mock.patch(\"tqdm.std.tqdm.display\", new=display_only_last))\n\n        def close_(self):\n            close(self)\n            with contextlib.suppress(KeyError):\n                displayed.remove(self)\n\n        patchers.append(mock.patch(\"tqdm.std.tqdm.close\", new=close_))\n\n        for patcher in patchers:\n            patcher.start()\n\n    class PysticheExampleTitleSortKey(ExampleTitleSortKey):\n        def __call__(self, filename):\n            # The beginner example *without* pystiche is placed before the example\n            # *with* to clarify the narrative.\n            if filename == \"example_nst_without_pystiche.py\":\n                return \"1\"\n            elif filename == \"example_nst_with_pystiche.py\":\n                return \"2\"\n            else:\n                return super().__call__(filename)\n\n    def filter_warnings():\n        # See #https://github.com/pytorch/pytorch/issues/60053\n        warnings.filterwarnings(\n            \"ignore\",\n            category=UserWarning,\n            message=(\n                re.escape(\n                    \"Named tensors and all their associated APIs are an experimental \"\n                    \"feature and subject to change. Please do not use them for \"\n                    \"anything important until they are released as stable. (Triggered \"\n                    \"internally at  /pytorch/c10/core/TensorImpl.h:1156.)\"\n                )\n            ),\n        )\n\n    if download_gallery:\n        download()\n\n    if plot_gallery and not torch.cuda.is_available():\n        msg = (\n            \"The galleries will be built, but CUDA is not available. \"\n            \"This will take a long time.\"\n        )\n        print(msg)\n\n    sphinx_gallery_conf = {\n        \"examples_dirs\": path.join(PROJECT_ROOT, \"examples\"),\n        \"gallery_dirs\": path.join(\"galleries\", \"examples\"),\n        \"filename_pattern\": re.escape(os.sep) + r\"example_\\w+[.]py$\",\n        \"ignore_pattern\": re.escape(os.sep) + r\"_\\w+[.]py$\",\n        \"line_numbers\": True,\n        \"remove_config_comments\": True,\n        \"plot_gallery\": plot_gallery,\n        \"subsection_order\": ExplicitOrder(\n            [\n                path.join(\"..\", \"..\", \"examples\", sub_gallery)\n                for sub_gallery in (\"beginner\", \"advanced\")\n            ]\n        ),\n        \"within_subsection_order\": PysticheExampleTitleSortKey,\n        \"show_memory\": show_cuda_memory if torch.cuda.is_available() else True,\n    }\n\n    config = dict(sphinx_gallery_conf=sphinx_gallery_conf)\n    filter_warnings()\n\n    patch_tqdm()\n    filter_warnings()\n\n    return extension, config\n\n\ndef logo():\n    extension = None\n\n    config = dict(html_logo=\"../../logo.svg\")\n\n    return extension, config\n\n\nextensions = []\nfor loader in (\n    project,\n    autodoc,\n    intersphinx,\n    html,\n    latex,\n    bibtex,\n    doctest,\n    sphinx_gallery,\n    logo,\n):\n    extension, config = loader()\n\n    if extension:\n        if isinstance(extension, str):\n            extension = (extension,)\n        extensions.extend(extension)\n\n    if config:\n        globals().update(config)\n", "path": "docs/source/conf.py"}], "after_files": [{"content": "import contextlib\nimport os\nimport re\nimport shutil\nimport warnings\nfrom datetime import datetime\nfrom distutils.util import strtobool\nfrom importlib_metadata import metadata as extract_metadata\nfrom os import path\nfrom unittest import mock\nfrom urllib.parse import urljoin\n\nfrom sphinx_gallery.sorting import ExampleTitleSortKey, ExplicitOrder\nfrom tqdm import tqdm\n\nimport torch\n\nfrom pystiche.misc import download_file\n\nHERE = path.dirname(__file__)\nPROJECT_ROOT = path.abspath(path.join(HERE, \"..\", \"..\"))\n\n\ndef get_bool_env_var(name, default=False):\n    try:\n        return bool(strtobool(os.environ[name]))\n    except KeyError:\n        return default\n\n\nGITHUB_ACTIONS = get_bool_env_var(\"GITHUB_ACTIONS\")\nRTD = get_bool_env_var(\"READTHEDOCS\")\nCI = GITHUB_ACTIONS or RTD or get_bool_env_var(\"CI\")\n\n\ndef project():\n    extension = None\n\n    metadata = extract_metadata(\"pystiche\")\n    project = metadata[\"name\"]\n    author = metadata[\"author\"]\n    copyright = f\"{datetime.now().year}, {author}\"\n    release = metadata[\"version\"]\n    version = release.split(\".dev\")[0]\n    config = dict(\n        project=project,\n        author=author,\n        copyright=copyright,\n        release=release,\n        version=version,\n    )\n\n    return extension, config\n\n\ndef autodoc():\n    extensions = [\n        \"sphinx.ext.autodoc\",\n        \"sphinx.ext.napoleon\",\n        \"sphinx_autodoc_typehints\",\n    ]\n\n    config = None\n\n    return extensions, config\n\n\ndef intersphinx():\n    extension = \"sphinx.ext.intersphinx\"\n    config = dict(\n        intersphinx_mapping={\n            \"python\": (\"https://docs.python.org/3.6\", None),\n            \"torch\": (\"https://pytorch.org/docs/stable/\", None),\n            \"torchvision\": (\"https://pytorch.org/docs/stable/\", None),\n            \"PIL\": (\"https://pillow.readthedocs.io/en/stable/\", None),\n            \"numpy\": (\"https://numpy.org/doc/1.18/\", None),\n            \"requests\": (\"https://requests.readthedocs.io/en/stable/\", None),\n            \"matplotlib\": (\"https://matplotlib.org\", None),\n        }\n    )\n    return extension, config\n\n\ndef html():\n    extension = None\n\n    config = dict(html_theme=\"sphinx_rtd_theme\")\n\n    return extension, config\n\n\ndef latex():\n    extension = None\n\n    with open(path.join(HERE, \"custom_cmds.tex\"), \"r\") as fh:\n        custom_cmds = fh.read()\n    config = dict(\n        latex_elements={\"preamble\": custom_cmds},\n        mathjax_inline=[r\"\\(\" + custom_cmds, r\"\\)\"],\n        mathjax_display=[r\"\\[\" + custom_cmds, r\"\\]\"],\n    )\n\n    return extension, config\n\n\ndef bibtex():\n    extension = \"sphinxcontrib.bibtex\"\n\n    config = dict(bibtex_bibfiles=[\"references.bib\"])\n\n    return extension, config\n\n\ndef doctest():\n    extension = \"sphinx.ext.doctest\"\n\n    doctest_global_setup = \"\"\"\nimport torch\nfrom torch import nn\n\nimport pystiche\n\nimport warnings\nwarnings.filterwarnings(\"ignore\", category=FutureWarning)\n\nfrom unittest import mock\n\npatcher = mock.patch(\n    \"pystiche.enc.models.utils.ModelMultiLayerEncoder.load_state_dict_from_url\"\n)\npatcher.start()\n\"\"\"\n\n    doctest_global_cleanup = \"\"\"\nmock.patch.stopall()\n\"\"\"\n    config = dict(\n        doctest_global_setup=doctest_global_setup,\n        doctest_global_cleanup=doctest_global_cleanup,\n    )\n\n    return extension, config\n\n\ndef sphinx_gallery():\n    extension = \"sphinx_gallery.gen_gallery\"\n\n    plot_gallery = get_bool_env_var(\"PYSTICHE_PLOT_GALLERY\", default=not CI)\n    download_gallery = get_bool_env_var(\"PYSTICHE_DOWNLOAD_GALLERY\", default=CI)\n\n    def download():\n        nonlocal extension\n        nonlocal plot_gallery\n\n        # version and release are available as soon as the project config is loaded\n        version = globals()[\"version\"]\n        release = globals()[\"release\"]\n\n        base = \"https://download.pystiche.org/galleries/\"\n        is_dev = version != release\n        file = \"main.zip\" if is_dev else f\"v{version}.zip\"\n\n        url = urljoin(base, file)\n        print(f\"Downloading pre-built galleries from {url}\")\n        download_file(url, file)\n\n        with contextlib.suppress(FileNotFoundError):\n            shutil.rmtree(path.join(HERE, \"galleries\"))\n        shutil.unpack_archive(file, extract_dir=\".\")\n        os.remove(file)\n\n        extension = \"sphinx_gallery.load_style\"\n        plot_gallery = False\n\n    def show_cuda_memory(func):\n        torch.cuda.reset_peak_memory_stats()\n        out = func()\n\n        stats = torch.cuda.memory_stats()\n        peak_bytes_usage = stats[\"allocated_bytes.all.peak\"]\n        memory = peak_bytes_usage / 1024 ** 2\n\n        return memory, out\n\n    def patch_tqdm():\n        patchers = [mock.patch(\"tqdm.std._supports_unicode\", return_value=True)]\n\n        display = tqdm.display\n        close = tqdm.close\n        displayed = set()\n\n        def display_only_last(self, msg=None, pos=None):\n            if self.n != self.total or self in displayed:\n                return\n\n            display(self, msg=msg, pos=pos)\n            displayed.add(self)\n\n        patchers.append(mock.patch(\"tqdm.std.tqdm.display\", new=display_only_last))\n\n        def close_(self):\n            close(self)\n            with contextlib.suppress(KeyError):\n                displayed.remove(self)\n\n        patchers.append(mock.patch(\"tqdm.std.tqdm.close\", new=close_))\n\n        for patcher in patchers:\n            patcher.start()\n\n    class PysticheExampleTitleSortKey(ExampleTitleSortKey):\n        def __call__(self, filename):\n            # The beginner example *without* pystiche is placed before the example\n            # *with* to clarify the narrative.\n            if filename == \"example_nst_without_pystiche.py\":\n                return \"1\"\n            elif filename == \"example_nst_with_pystiche.py\":\n                return \"2\"\n            else:\n                return super().__call__(filename)\n\n    def filter_warnings():\n        # See #https://github.com/pytorch/pytorch/issues/60053\n        warnings.filterwarnings(\n            \"ignore\",\n            category=UserWarning,\n            message=(\n                re.escape(\n                    \"Named tensors and all their associated APIs are an experimental \"\n                    \"feature and subject to change. Please do not use them for \"\n                    \"anything important until they are released as stable. (Triggered \"\n                    \"internally at  /pytorch/c10/core/TensorImpl.h:1156.)\"\n                )\n            ),\n        )\n\n    if download_gallery:\n        download()\n\n    if plot_gallery and not torch.cuda.is_available():\n        msg = (\n            \"The galleries will be built, but CUDA is not available. \"\n            \"This will take a long time.\"\n        )\n        print(msg)\n\n    sphinx_gallery_conf = {\n        \"examples_dirs\": path.join(PROJECT_ROOT, \"examples\"),\n        \"gallery_dirs\": path.join(\"galleries\", \"examples\"),\n        \"filename_pattern\": re.escape(os.sep) + r\"example_\\w+[.]py$\",\n        \"ignore_pattern\": re.escape(os.sep) + r\"_\\w+[.]py$\",\n        \"line_numbers\": True,\n        \"remove_config_comments\": True,\n        \"plot_gallery\": plot_gallery,\n        \"subsection_order\": ExplicitOrder(\n            [\n                path.join(\"..\", \"..\", \"examples\", sub_gallery)\n                for sub_gallery in (\"beginner\", \"advanced\")\n            ]\n        ),\n        \"within_subsection_order\": PysticheExampleTitleSortKey,\n        \"show_memory\": show_cuda_memory if torch.cuda.is_available() else True,\n    }\n\n    config = dict(sphinx_gallery_conf=sphinx_gallery_conf)\n    filter_warnings()\n\n    patch_tqdm()\n    filter_warnings()\n\n    return extension, config\n\n\ndef logo():\n    extension = None\n\n    config = dict(html_logo=\"../../logo.svg\")\n\n    return extension, config\n\n\nextensions = []\nfor loader in (\n    project,\n    autodoc,\n    intersphinx,\n    html,\n    latex,\n    bibtex,\n    doctest,\n    sphinx_gallery,\n    logo,\n):\n    extension, config = loader()\n\n    if extension:\n        if isinstance(extension, str):\n            extension = (extension,)\n        extensions.extend(extension)\n\n    if config:\n        globals().update(config)\n", "path": "docs/source/conf.py"}]}