forked from jazzband/pip-tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwriter.py
151 lines (130 loc) · 6.12 KB
/
writer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import os
from itertools import chain
from ._compat import ExitStack
from .click import unstyle
from .io import AtomicSaver
from .logging import log
from .utils import comment, dedup, format_requirement, key_from_req, UNSAFE_PACKAGES
class OutputWriter(object):
def __init__(self, src_files, dst_file, dry_run, emit_header, emit_index,
emit_trusted_host, annotate, generate_hashes,
default_index_url, index_urls, trusted_hosts, format_control):
self.src_files = src_files
self.dst_file = dst_file
self.dry_run = dry_run
self.emit_header = emit_header
self.emit_index = emit_index
self.emit_trusted_host = emit_trusted_host
self.annotate = annotate
self.generate_hashes = generate_hashes
self.default_index_url = default_index_url
self.index_urls = index_urls
self.trusted_hosts = trusted_hosts
self.format_control = format_control
def _sort_key(self, ireq):
return (not ireq.editable, str(ireq.req).lower())
def write_header(self):
if self.emit_header:
yield comment('#')
yield comment('# This file is autogenerated by pip-compile')
yield comment('# To update, run:')
yield comment('#')
custom_cmd = os.environ.get('CUSTOM_COMPILE_COMMAND')
if custom_cmd:
yield comment('# {}'.format(custom_cmd))
else:
params = []
if not self.emit_index:
params += ['--no-index']
if not self.emit_trusted_host:
params += ['--no-emit-trusted-host']
if not self.annotate:
params += ['--no-annotate']
if self.generate_hashes:
params += ["--generate-hashes"]
params += ['--output-file', self.dst_file]
params += self.src_files
yield comment('# pip-compile {}'.format(' '.join(params)))
yield comment('#')
def write_index_options(self):
if self.emit_index:
for index, index_url in enumerate(dedup(self.index_urls)):
if index_url.rstrip('/') == self.default_index_url:
continue
flag = '--index-url' if index == 0 else '--extra-index-url'
yield '{} {}'.format(flag, index_url)
def write_trusted_hosts(self):
if self.emit_trusted_host:
for trusted_host in dedup(self.trusted_hosts):
yield '--trusted-host {}'.format(trusted_host)
def write_format_controls(self):
for nb in dedup(self.format_control.no_binary):
yield '--no-binary {}'.format(nb)
for ob in dedup(self.format_control.only_binary):
yield '--only-binary {}'.format(ob)
def write_flags(self):
emitted = False
for line in chain(self.write_index_options(),
self.write_trusted_hosts(),
self.write_format_controls()):
emitted = True
yield line
if emitted:
yield ''
def _iter_lines(self, results, unsafe_requirements, reverse_dependencies,
primary_packages, markers, hashes, allow_unsafe=False):
for line in self.write_header():
yield line
for line in self.write_flags():
yield line
unsafe_requirements = {r for r in results if r.name in UNSAFE_PACKAGES} if not unsafe_requirements else unsafe_requirements # noqa
packages = {r for r in results if r.name not in UNSAFE_PACKAGES}
packages = sorted(packages, key=self._sort_key)
for ireq in packages:
line = self._format_requirement(
ireq, reverse_dependencies, primary_packages,
markers.get(key_from_req(ireq.req)), hashes=hashes)
yield line
if unsafe_requirements:
unsafe_requirements = sorted(unsafe_requirements, key=self._sort_key)
yield ''
yield comment('# The following packages are considered to be unsafe in a requirements file:')
for ireq in unsafe_requirements:
req = self._format_requirement(ireq,
reverse_dependencies,
primary_packages,
marker=markers.get(key_from_req(ireq.req)),
hashes=hashes)
if not allow_unsafe:
yield comment('# {}'.format(req))
else:
yield req
def write(self, results, unsafe_requirements, reverse_dependencies,
primary_packages, markers, hashes, allow_unsafe=False):
with ExitStack() as stack:
f = None
if not self.dry_run:
f = stack.enter_context(AtomicSaver(self.dst_file))
for line in self._iter_lines(results, unsafe_requirements, reverse_dependencies,
primary_packages, markers, hashes, allow_unsafe=allow_unsafe):
log.info(line)
if f:
f.write(unstyle(line).encode('utf-8'))
f.write(os.linesep.encode('utf-8'))
def _format_requirement(self, ireq, reverse_dependencies, primary_packages, marker=None, hashes=None):
line = format_requirement(ireq, marker=marker)
ireq_hashes = (hashes if hashes is not None else {}).get(ireq)
if ireq_hashes:
for hash_ in sorted(ireq_hashes):
line += " \\\n --hash={}".format(hash_)
if not self.annotate or key_from_req(ireq.req) in primary_packages:
return line
# Annotate what packages this package is required by
required_by = reverse_dependencies.get(ireq.name.lower(), [])
if required_by:
annotation = ", ".join(sorted(required_by))
line = "{:24}{}{}".format(
line,
" \\\n " if ireq_hashes else " ",
comment("# via " + annotation))
return line