We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
log which python version to use/was used
eg add this to the header:

```
 # This file is autogenerated by pip-compile on:
 # Python 2.7.15+ (default, Oct  2 2018, 22:12:08) 
 # [GCC 8.2.0] on linux2
 # To update, run:
 #
 #    pip-compile --generate-hashes --output-file=requirements.txt requirements.in
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `piptools/writer.py`
Content:
```
1 import os
2 import re
3 from itertools import chain
4 from typing import BinaryIO, Dict, Iterable, Iterator, List, Optional, Set, Tuple
5 
6 from click import unstyle
7 from click.core import Context
8 from pip._internal.models.format_control import FormatControl
9 from pip._internal.req.req_install import InstallRequirement
10 from pip._vendor.packaging.markers import Marker
11 
12 from .logging import log
13 from .utils import (
14     UNSAFE_PACKAGES,
15     comment,
16     dedup,
17     format_requirement,
18     get_compile_command,
19     key_from_ireq,
20 )
21 
22 MESSAGE_UNHASHED_PACKAGE = comment(
23     "# WARNING: pip install will require the following package to be hashed."
24     "\n# Consider using a hashable URL like "
25     "https://github.com/jazzband/pip-tools/archive/SOMECOMMIT.zip"
26 )
27 
28 MESSAGE_UNSAFE_PACKAGES_UNPINNED = comment(
29     "# WARNING: The following packages were not pinned, but pip requires them to be"
30     "\n# pinned when the requirements file includes hashes. "
31     "Consider using the --allow-unsafe flag."
32 )
33 
34 MESSAGE_UNSAFE_PACKAGES = comment(
35     "# The following packages are considered to be unsafe in a requirements file:"
36 )
37 
38 MESSAGE_UNINSTALLABLE = (
39     "The generated requirements file may be rejected by pip install. "
40     "See # WARNING lines for details."
41 )
42 
43 
44 strip_comes_from_line_re = re.compile(r" \(line \d+\)$")
45 
46 
47 def _comes_from_as_string(ireq: InstallRequirement) -> str:
48     if isinstance(ireq.comes_from, str):
49         return strip_comes_from_line_re.sub("", ireq.comes_from)
50     return key_from_ireq(ireq.comes_from)
51 
52 
53 class OutputWriter:
54     def __init__(
55         self,
56         dst_file: BinaryIO,
57         click_ctx: Context,
58         dry_run: bool,
59         emit_header: bool,
60         emit_index_url: bool,
61         emit_trusted_host: bool,
62         annotate: bool,
63         generate_hashes: bool,
64         default_index_url: str,
65         index_urls: Iterable[str],
66         trusted_hosts: Iterable[str],
67         format_control: FormatControl,
68         allow_unsafe: bool,
69         find_links: List[str],
70         emit_find_links: bool,
71     ) -> None:
72         self.dst_file = dst_file
73         self.click_ctx = click_ctx
74         self.dry_run = dry_run
75         self.emit_header = emit_header
76         self.emit_index_url = emit_index_url
77         self.emit_trusted_host = emit_trusted_host
78         self.annotate = annotate
79         self.generate_hashes = generate_hashes
80         self.default_index_url = default_index_url
81         self.index_urls = index_urls
82         self.trusted_hosts = trusted_hosts
83         self.format_control = format_control
84         self.allow_unsafe = allow_unsafe
85         self.find_links = find_links
86         self.emit_find_links = emit_find_links
87 
88     def _sort_key(self, ireq: InstallRequirement) -> Tuple[bool, str]:
89         return (not ireq.editable, str(ireq.req).lower())
90 
91     def write_header(self) -> Iterator[str]:
92         if self.emit_header:
93             yield comment("#")
94             yield comment("# This file is autogenerated by pip-compile")
95             yield comment("# To update, run:")
96             yield comment("#")
97             compile_command = os.environ.get(
98                 "CUSTOM_COMPILE_COMMAND"
99             ) or get_compile_command(self.click_ctx)
100             yield comment(f"#    {compile_command}")
101             yield comment("#")
102 
103     def write_index_options(self) -> Iterator[str]:
104         if self.emit_index_url:
105             for index, index_url in enumerate(dedup(self.index_urls)):
106                 if index == 0 and index_url.rstrip("/") == self.default_index_url:
107                     continue
108                 flag = "--index-url" if index == 0 else "--extra-index-url"
109                 yield f"{flag} {index_url}"
110 
111     def write_trusted_hosts(self) -> Iterator[str]:
112         if self.emit_trusted_host:
113             for trusted_host in dedup(self.trusted_hosts):
114                 yield f"--trusted-host {trusted_host}"
115 
116     def write_format_controls(self) -> Iterator[str]:
117         for nb in dedup(sorted(self.format_control.no_binary)):
118             yield f"--no-binary {nb}"
119         for ob in dedup(sorted(self.format_control.only_binary)):
120             yield f"--only-binary {ob}"
121 
122     def write_find_links(self) -> Iterator[str]:
123         if self.emit_find_links:
124             for find_link in dedup(self.find_links):
125                 yield f"--find-links {find_link}"
126 
127     def write_flags(self) -> Iterator[str]:
128         emitted = False
129         for line in chain(
130             self.write_index_options(),
131             self.write_find_links(),
132             self.write_trusted_hosts(),
133             self.write_format_controls(),
134         ):
135             emitted = True
136             yield line
137         if emitted:
138             yield ""
139 
140     def _iter_lines(
141         self,
142         results: Set[InstallRequirement],
143         unsafe_requirements: Optional[Set[InstallRequirement]] = None,
144         markers: Optional[Dict[str, Marker]] = None,
145         hashes: Optional[Dict[InstallRequirement, Set[str]]] = None,
146     ) -> Iterator[str]:
147         # default values
148         unsafe_requirements = unsafe_requirements or set()
149         markers = markers or {}
150         hashes = hashes or {}
151 
152         # Check for unhashed or unpinned packages if at least one package does have
153         # hashes, which will trigger pip install's --require-hashes mode.
154         warn_uninstallable = False
155         has_hashes = hashes and any(hash for hash in hashes.values())
156 
157         yielded = False
158 
159         for line in self.write_header():
160             yield line
161             yielded = True
162         for line in self.write_flags():
163             yield line
164             yielded = True
165 
166         unsafe_requirements = (
167             {r for r in results if r.name in UNSAFE_PACKAGES}
168             if not unsafe_requirements
169             else unsafe_requirements
170         )
171         packages = {r for r in results if r.name not in UNSAFE_PACKAGES}
172 
173         if packages:
174             for ireq in sorted(packages, key=self._sort_key):
175                 if has_hashes and not hashes.get(ireq):
176                     yield MESSAGE_UNHASHED_PACKAGE
177                     warn_uninstallable = True
178                 line = self._format_requirement(
179                     ireq, markers.get(key_from_ireq(ireq)), hashes=hashes
180                 )
181                 yield line
182             yielded = True
183 
184         if unsafe_requirements:
185             yield ""
186             yielded = True
187             if has_hashes and not self.allow_unsafe:
188                 yield MESSAGE_UNSAFE_PACKAGES_UNPINNED
189                 warn_uninstallable = True
190             else:
191                 yield MESSAGE_UNSAFE_PACKAGES
192 
193             for ireq in sorted(unsafe_requirements, key=self._sort_key):
194                 ireq_key = key_from_ireq(ireq)
195                 if not self.allow_unsafe:
196                     yield comment(f"# {ireq_key}")
197                 else:
198                     line = self._format_requirement(
199                         ireq, marker=markers.get(ireq_key), hashes=hashes
200                     )
201                     yield line
202 
203         # Yield even when there's no real content, so that blank files are written
204         if not yielded:
205             yield ""
206 
207         if warn_uninstallable:
208             log.warning(MESSAGE_UNINSTALLABLE)
209 
210     def write(
211         self,
212         results: Set[InstallRequirement],
213         unsafe_requirements: Set[InstallRequirement],
214         markers: Dict[str, Marker],
215         hashes: Optional[Dict[InstallRequirement, Set[str]]],
216     ) -> None:
217 
218         for line in self._iter_lines(results, unsafe_requirements, markers, hashes):
219             log.info(line)
220             if not self.dry_run:
221                 self.dst_file.write(unstyle(line).encode())
222                 self.dst_file.write(os.linesep.encode())
223 
224     def _format_requirement(
225         self,
226         ireq: InstallRequirement,
227         marker: Optional[Marker] = None,
228         hashes: Optional[Dict[InstallRequirement, Set[str]]] = None,
229     ) -> str:
230         ireq_hashes = (hashes if hashes is not None else {}).get(ireq)
231 
232         line = format_requirement(ireq, marker=marker, hashes=ireq_hashes)
233 
234         if not self.annotate:
235             return line
236 
237         # Annotate what packages or reqs-ins this package is required by
238         required_by = set()
239         if hasattr(ireq, "_source_ireqs"):
240             required_by |= {
241                 _comes_from_as_string(src_ireq)
242                 for src_ireq in ireq._source_ireqs
243                 if src_ireq.comes_from
244             }
245         elif ireq.comes_from:
246             required_by.add(_comes_from_as_string(ireq))
247 
248         if required_by:
249             sorted_required_by = sorted(required_by)
250             if len(sorted_required_by) == 1:
251                 source = sorted_required_by[0]
252                 annotation = "    # via " + source
253             else:
254                 annotation_lines = ["    # via"]
255                 for source in sorted_required_by:
256                     annotation_lines.append("    #   " + source)
257                 annotation = "\n".join(annotation_lines)
258             line = f"{line}\n{comment(annotation)}"
259 
260         return line
261
```
--- 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/piptools/writer.py b/piptools/writer.py
--- a/piptools/writer.py
+++ b/piptools/writer.py
@@ -1,5 +1,6 @@
 import os
 import re
+import sys
 from itertools import chain
 from typing import BinaryIO, Dict, Iterable, Iterator, List, Optional, Set, Tuple
 
@@ -91,7 +92,10 @@
     def write_header(self) -> Iterator[str]:
         if self.emit_header:
             yield comment("#")
-            yield comment("# This file is autogenerated by pip-compile")
+            yield comment(
+                "# This file is autogenerated by pip-compile with python "
+                f"{sys.version_info.major}.{sys.version_info.minor}"
+            )
             yield comment("# To update, run:")
             yield comment("#")
             compile_command = os.environ.get(

{"golden_diff": "diff --git a/piptools/writer.py b/piptools/writer.py\n--- a/piptools/writer.py\n+++ b/piptools/writer.py\n@@ -1,5 +1,6 @@\n import os\n import re\n+import sys\n from itertools import chain\n from typing import BinaryIO, Dict, Iterable, Iterator, List, Optional, Set, Tuple\n \n@@ -91,7 +92,10 @@\n     def write_header(self) -> Iterator[str]:\n         if self.emit_header:\n             yield comment(\"#\")\n-            yield comment(\"# This file is autogenerated by pip-compile\")\n+            yield comment(\n+                \"# This file is autogenerated by pip-compile with python \"\n+                f\"{sys.version_info.major}.{sys.version_info.minor}\"\n+            )\n             yield comment(\"# To update, run:\")\n             yield comment(\"#\")\n             compile_command = os.environ.get(\n", "issue": "log which python version to use/was used\neg add this to the header:\r\n\r\n```\r\n # This file is autogenerated by pip-compile on:\r\n # Python 2.7.15+ (default, Oct  2 2018, 22:12:08) \r\n # [GCC 8.2.0] on linux2\r\n # To update, run:\r\n #\r\n #    pip-compile --generate-hashes --output-file=requirements.txt requirements.in\r\n```\n", "before_files": [{"content": "import os\nimport re\nfrom itertools import chain\nfrom typing import BinaryIO, Dict, Iterable, Iterator, List, Optional, Set, Tuple\n\nfrom click import unstyle\nfrom click.core import Context\nfrom pip._internal.models.format_control import FormatControl\nfrom pip._internal.req.req_install import InstallRequirement\nfrom pip._vendor.packaging.markers import Marker\n\nfrom .logging import log\nfrom .utils import (\n    UNSAFE_PACKAGES,\n    comment,\n    dedup,\n    format_requirement,\n    get_compile_command,\n    key_from_ireq,\n)\n\nMESSAGE_UNHASHED_PACKAGE = comment(\n    \"# WARNING: pip install will require the following package to be hashed.\"\n    \"\\n# Consider using a hashable URL like \"\n    \"https://github.com/jazzband/pip-tools/archive/SOMECOMMIT.zip\"\n)\n\nMESSAGE_UNSAFE_PACKAGES_UNPINNED = comment(\n    \"# WARNING: The following packages were not pinned, but pip requires them to be\"\n    \"\\n# pinned when the requirements file includes hashes. \"\n    \"Consider using the --allow-unsafe flag.\"\n)\n\nMESSAGE_UNSAFE_PACKAGES = comment(\n    \"# The following packages are considered to be unsafe in a requirements file:\"\n)\n\nMESSAGE_UNINSTALLABLE = (\n    \"The generated requirements file may be rejected by pip install. \"\n    \"See # WARNING lines for details.\"\n)\n\n\nstrip_comes_from_line_re = re.compile(r\" \\(line \\d+\\)$\")\n\n\ndef _comes_from_as_string(ireq: InstallRequirement) -> str:\n    if isinstance(ireq.comes_from, str):\n        return strip_comes_from_line_re.sub(\"\", ireq.comes_from)\n    return key_from_ireq(ireq.comes_from)\n\n\nclass OutputWriter:\n    def __init__(\n        self,\n        dst_file: BinaryIO,\n        click_ctx: Context,\n        dry_run: bool,\n        emit_header: bool,\n        emit_index_url: bool,\n        emit_trusted_host: bool,\n        annotate: bool,\n        generate_hashes: bool,\n        default_index_url: str,\n        index_urls: Iterable[str],\n        trusted_hosts: Iterable[str],\n        format_control: FormatControl,\n        allow_unsafe: bool,\n        find_links: List[str],\n        emit_find_links: bool,\n    ) -> None:\n        self.dst_file = dst_file\n        self.click_ctx = click_ctx\n        self.dry_run = dry_run\n        self.emit_header = emit_header\n        self.emit_index_url = emit_index_url\n        self.emit_trusted_host = emit_trusted_host\n        self.annotate = annotate\n        self.generate_hashes = generate_hashes\n        self.default_index_url = default_index_url\n        self.index_urls = index_urls\n        self.trusted_hosts = trusted_hosts\n        self.format_control = format_control\n        self.allow_unsafe = allow_unsafe\n        self.find_links = find_links\n        self.emit_find_links = emit_find_links\n\n    def _sort_key(self, ireq: InstallRequirement) -> Tuple[bool, str]:\n        return (not ireq.editable, str(ireq.req).lower())\n\n    def write_header(self) -> Iterator[str]:\n        if self.emit_header:\n            yield comment(\"#\")\n            yield comment(\"# This file is autogenerated by pip-compile\")\n            yield comment(\"# To update, run:\")\n            yield comment(\"#\")\n            compile_command = os.environ.get(\n                \"CUSTOM_COMPILE_COMMAND\"\n            ) or get_compile_command(self.click_ctx)\n            yield comment(f\"#    {compile_command}\")\n            yield comment(\"#\")\n\n    def write_index_options(self) -> Iterator[str]:\n        if self.emit_index_url:\n            for index, index_url in enumerate(dedup(self.index_urls)):\n                if index == 0 and index_url.rstrip(\"/\") == self.default_index_url:\n                    continue\n                flag = \"--index-url\" if index == 0 else \"--extra-index-url\"\n                yield f\"{flag} {index_url}\"\n\n    def write_trusted_hosts(self) -> Iterator[str]:\n        if self.emit_trusted_host:\n            for trusted_host in dedup(self.trusted_hosts):\n                yield f\"--trusted-host {trusted_host}\"\n\n    def write_format_controls(self) -> Iterator[str]:\n        for nb in dedup(sorted(self.format_control.no_binary)):\n            yield f\"--no-binary {nb}\"\n        for ob in dedup(sorted(self.format_control.only_binary)):\n            yield f\"--only-binary {ob}\"\n\n    def write_find_links(self) -> Iterator[str]:\n        if self.emit_find_links:\n            for find_link in dedup(self.find_links):\n                yield f\"--find-links {find_link}\"\n\n    def write_flags(self) -> Iterator[str]:\n        emitted = False\n        for line in chain(\n            self.write_index_options(),\n            self.write_find_links(),\n            self.write_trusted_hosts(),\n            self.write_format_controls(),\n        ):\n            emitted = True\n            yield line\n        if emitted:\n            yield \"\"\n\n    def _iter_lines(\n        self,\n        results: Set[InstallRequirement],\n        unsafe_requirements: Optional[Set[InstallRequirement]] = None,\n        markers: Optional[Dict[str, Marker]] = None,\n        hashes: Optional[Dict[InstallRequirement, Set[str]]] = None,\n    ) -> Iterator[str]:\n        # default values\n        unsafe_requirements = unsafe_requirements or set()\n        markers = markers or {}\n        hashes = hashes or {}\n\n        # Check for unhashed or unpinned packages if at least one package does have\n        # hashes, which will trigger pip install's --require-hashes mode.\n        warn_uninstallable = False\n        has_hashes = hashes and any(hash for hash in hashes.values())\n\n        yielded = False\n\n        for line in self.write_header():\n            yield line\n            yielded = True\n        for line in self.write_flags():\n            yield line\n            yielded = True\n\n        unsafe_requirements = (\n            {r for r in results if r.name in UNSAFE_PACKAGES}\n            if not unsafe_requirements\n            else unsafe_requirements\n        )\n        packages = {r for r in results if r.name not in UNSAFE_PACKAGES}\n\n        if packages:\n            for ireq in sorted(packages, key=self._sort_key):\n                if has_hashes and not hashes.get(ireq):\n                    yield MESSAGE_UNHASHED_PACKAGE\n                    warn_uninstallable = True\n                line = self._format_requirement(\n                    ireq, markers.get(key_from_ireq(ireq)), hashes=hashes\n                )\n                yield line\n            yielded = True\n\n        if unsafe_requirements:\n            yield \"\"\n            yielded = True\n            if has_hashes and not self.allow_unsafe:\n                yield MESSAGE_UNSAFE_PACKAGES_UNPINNED\n                warn_uninstallable = True\n            else:\n                yield MESSAGE_UNSAFE_PACKAGES\n\n            for ireq in sorted(unsafe_requirements, key=self._sort_key):\n                ireq_key = key_from_ireq(ireq)\n                if not self.allow_unsafe:\n                    yield comment(f\"# {ireq_key}\")\n                else:\n                    line = self._format_requirement(\n                        ireq, marker=markers.get(ireq_key), hashes=hashes\n                    )\n                    yield line\n\n        # Yield even when there's no real content, so that blank files are written\n        if not yielded:\n            yield \"\"\n\n        if warn_uninstallable:\n            log.warning(MESSAGE_UNINSTALLABLE)\n\n    def write(\n        self,\n        results: Set[InstallRequirement],\n        unsafe_requirements: Set[InstallRequirement],\n        markers: Dict[str, Marker],\n        hashes: Optional[Dict[InstallRequirement, Set[str]]],\n    ) -> None:\n\n        for line in self._iter_lines(results, unsafe_requirements, markers, hashes):\n            log.info(line)\n            if not self.dry_run:\n                self.dst_file.write(unstyle(line).encode())\n                self.dst_file.write(os.linesep.encode())\n\n    def _format_requirement(\n        self,\n        ireq: InstallRequirement,\n        marker: Optional[Marker] = None,\n        hashes: Optional[Dict[InstallRequirement, Set[str]]] = None,\n    ) -> str:\n        ireq_hashes = (hashes if hashes is not None else {}).get(ireq)\n\n        line = format_requirement(ireq, marker=marker, hashes=ireq_hashes)\n\n        if not self.annotate:\n            return line\n\n        # Annotate what packages or reqs-ins this package is required by\n        required_by = set()\n        if hasattr(ireq, \"_source_ireqs\"):\n            required_by |= {\n                _comes_from_as_string(src_ireq)\n                for src_ireq in ireq._source_ireqs\n                if src_ireq.comes_from\n            }\n        elif ireq.comes_from:\n            required_by.add(_comes_from_as_string(ireq))\n\n        if required_by:\n            sorted_required_by = sorted(required_by)\n            if len(sorted_required_by) == 1:\n                source = sorted_required_by[0]\n                annotation = \"    # via \" + source\n            else:\n                annotation_lines = [\"    # via\"]\n                for source in sorted_required_by:\n                    annotation_lines.append(\"    #   \" + source)\n                annotation = \"\\n\".join(annotation_lines)\n            line = f\"{line}\\n{comment(annotation)}\"\n\n        return line\n", "path": "piptools/writer.py"}], "after_files": [{"content": "import os\nimport re\nimport sys\nfrom itertools import chain\nfrom typing import BinaryIO, Dict, Iterable, Iterator, List, Optional, Set, Tuple\n\nfrom click import unstyle\nfrom click.core import Context\nfrom pip._internal.models.format_control import FormatControl\nfrom pip._internal.req.req_install import InstallRequirement\nfrom pip._vendor.packaging.markers import Marker\n\nfrom .logging import log\nfrom .utils import (\n    UNSAFE_PACKAGES,\n    comment,\n    dedup,\n    format_requirement,\n    get_compile_command,\n    key_from_ireq,\n)\n\nMESSAGE_UNHASHED_PACKAGE = comment(\n    \"# WARNING: pip install will require the following package to be hashed.\"\n    \"\\n# Consider using a hashable URL like \"\n    \"https://github.com/jazzband/pip-tools/archive/SOMECOMMIT.zip\"\n)\n\nMESSAGE_UNSAFE_PACKAGES_UNPINNED = comment(\n    \"# WARNING: The following packages were not pinned, but pip requires them to be\"\n    \"\\n# pinned when the requirements file includes hashes. \"\n    \"Consider using the --allow-unsafe flag.\"\n)\n\nMESSAGE_UNSAFE_PACKAGES = comment(\n    \"# The following packages are considered to be unsafe in a requirements file:\"\n)\n\nMESSAGE_UNINSTALLABLE = (\n    \"The generated requirements file may be rejected by pip install. \"\n    \"See # WARNING lines for details.\"\n)\n\n\nstrip_comes_from_line_re = re.compile(r\" \\(line \\d+\\)$\")\n\n\ndef _comes_from_as_string(ireq: InstallRequirement) -> str:\n    if isinstance(ireq.comes_from, str):\n        return strip_comes_from_line_re.sub(\"\", ireq.comes_from)\n    return key_from_ireq(ireq.comes_from)\n\n\nclass OutputWriter:\n    def __init__(\n        self,\n        dst_file: BinaryIO,\n        click_ctx: Context,\n        dry_run: bool,\n        emit_header: bool,\n        emit_index_url: bool,\n        emit_trusted_host: bool,\n        annotate: bool,\n        generate_hashes: bool,\n        default_index_url: str,\n        index_urls: Iterable[str],\n        trusted_hosts: Iterable[str],\n        format_control: FormatControl,\n        allow_unsafe: bool,\n        find_links: List[str],\n        emit_find_links: bool,\n    ) -> None:\n        self.dst_file = dst_file\n        self.click_ctx = click_ctx\n        self.dry_run = dry_run\n        self.emit_header = emit_header\n        self.emit_index_url = emit_index_url\n        self.emit_trusted_host = emit_trusted_host\n        self.annotate = annotate\n        self.generate_hashes = generate_hashes\n        self.default_index_url = default_index_url\n        self.index_urls = index_urls\n        self.trusted_hosts = trusted_hosts\n        self.format_control = format_control\n        self.allow_unsafe = allow_unsafe\n        self.find_links = find_links\n        self.emit_find_links = emit_find_links\n\n    def _sort_key(self, ireq: InstallRequirement) -> Tuple[bool, str]:\n        return (not ireq.editable, str(ireq.req).lower())\n\n    def write_header(self) -> Iterator[str]:\n        if self.emit_header:\n            yield comment(\"#\")\n            yield comment(\n                \"# This file is autogenerated by pip-compile with python \"\n                f\"{sys.version_info.major}.{sys.version_info.minor}\"\n            )\n            yield comment(\"# To update, run:\")\n            yield comment(\"#\")\n            compile_command = os.environ.get(\n                \"CUSTOM_COMPILE_COMMAND\"\n            ) or get_compile_command(self.click_ctx)\n            yield comment(f\"#    {compile_command}\")\n            yield comment(\"#\")\n\n    def write_index_options(self) -> Iterator[str]:\n        if self.emit_index_url:\n            for index, index_url in enumerate(dedup(self.index_urls)):\n                if index == 0 and index_url.rstrip(\"/\") == self.default_index_url:\n                    continue\n                flag = \"--index-url\" if index == 0 else \"--extra-index-url\"\n                yield f\"{flag} {index_url}\"\n\n    def write_trusted_hosts(self) -> Iterator[str]:\n        if self.emit_trusted_host:\n            for trusted_host in dedup(self.trusted_hosts):\n                yield f\"--trusted-host {trusted_host}\"\n\n    def write_format_controls(self) -> Iterator[str]:\n        for nb in dedup(sorted(self.format_control.no_binary)):\n            yield f\"--no-binary {nb}\"\n        for ob in dedup(sorted(self.format_control.only_binary)):\n            yield f\"--only-binary {ob}\"\n\n    def write_find_links(self) -> Iterator[str]:\n        if self.emit_find_links:\n            for find_link in dedup(self.find_links):\n                yield f\"--find-links {find_link}\"\n\n    def write_flags(self) -> Iterator[str]:\n        emitted = False\n        for line in chain(\n            self.write_index_options(),\n            self.write_find_links(),\n            self.write_trusted_hosts(),\n            self.write_format_controls(),\n        ):\n            emitted = True\n            yield line\n        if emitted:\n            yield \"\"\n\n    def _iter_lines(\n        self,\n        results: Set[InstallRequirement],\n        unsafe_requirements: Optional[Set[InstallRequirement]] = None,\n        markers: Optional[Dict[str, Marker]] = None,\n        hashes: Optional[Dict[InstallRequirement, Set[str]]] = None,\n    ) -> Iterator[str]:\n        # default values\n        unsafe_requirements = unsafe_requirements or set()\n        markers = markers or {}\n        hashes = hashes or {}\n\n        # Check for unhashed or unpinned packages if at least one package does have\n        # hashes, which will trigger pip install's --require-hashes mode.\n        warn_uninstallable = False\n        has_hashes = hashes and any(hash for hash in hashes.values())\n\n        yielded = False\n\n        for line in self.write_header():\n            yield line\n            yielded = True\n        for line in self.write_flags():\n            yield line\n            yielded = True\n\n        unsafe_requirements = (\n            {r for r in results if r.name in UNSAFE_PACKAGES}\n            if not unsafe_requirements\n            else unsafe_requirements\n        )\n        packages = {r for r in results if r.name not in UNSAFE_PACKAGES}\n\n        if packages:\n            for ireq in sorted(packages, key=self._sort_key):\n                if has_hashes and not hashes.get(ireq):\n                    yield MESSAGE_UNHASHED_PACKAGE\n                    warn_uninstallable = True\n                line = self._format_requirement(\n                    ireq, markers.get(key_from_ireq(ireq)), hashes=hashes\n                )\n                yield line\n            yielded = True\n\n        if unsafe_requirements:\n            yield \"\"\n            yielded = True\n            if has_hashes and not self.allow_unsafe:\n                yield MESSAGE_UNSAFE_PACKAGES_UNPINNED\n                warn_uninstallable = True\n            else:\n                yield MESSAGE_UNSAFE_PACKAGES\n\n            for ireq in sorted(unsafe_requirements, key=self._sort_key):\n                ireq_key = key_from_ireq(ireq)\n                if not self.allow_unsafe:\n                    yield comment(f\"# {ireq_key}\")\n                else:\n                    line = self._format_requirement(\n                        ireq, marker=markers.get(ireq_key), hashes=hashes\n                    )\n                    yield line\n\n        # Yield even when there's no real content, so that blank files are written\n        if not yielded:\n            yield \"\"\n\n        if warn_uninstallable:\n            log.warning(MESSAGE_UNINSTALLABLE)\n\n    def write(\n        self,\n        results: Set[InstallRequirement],\n        unsafe_requirements: Set[InstallRequirement],\n        markers: Dict[str, Marker],\n        hashes: Optional[Dict[InstallRequirement, Set[str]]],\n    ) -> None:\n\n        for line in self._iter_lines(results, unsafe_requirements, markers, hashes):\n            log.info(line)\n            if not self.dry_run:\n                self.dst_file.write(unstyle(line).encode())\n                self.dst_file.write(os.linesep.encode())\n\n    def _format_requirement(\n        self,\n        ireq: InstallRequirement,\n        marker: Optional[Marker] = None,\n        hashes: Optional[Dict[InstallRequirement, Set[str]]] = None,\n    ) -> str:\n        ireq_hashes = (hashes if hashes is not None else {}).get(ireq)\n\n        line = format_requirement(ireq, marker=marker, hashes=ireq_hashes)\n\n        if not self.annotate:\n            return line\n\n        # Annotate what packages or reqs-ins this package is required by\n        required_by = set()\n        if hasattr(ireq, \"_source_ireqs\"):\n            required_by |= {\n                _comes_from_as_string(src_ireq)\n                for src_ireq in ireq._source_ireqs\n                if src_ireq.comes_from\n            }\n        elif ireq.comes_from:\n            required_by.add(_comes_from_as_string(ireq))\n\n        if required_by:\n            sorted_required_by = sorted(required_by)\n            if len(sorted_required_by) == 1:\n                source = sorted_required_by[0]\n                annotation = \"    # via \" + source\n            else:\n                annotation_lines = [\"    # via\"]\n                for source in sorted_required_by:\n                    annotation_lines.append(\"    #   \" + source)\n                annotation = \"\\n\".join(annotation_lines)\n            line = f\"{line}\\n{comment(annotation)}\"\n\n        return line\n", "path": "piptools/writer.py"}]}