Gentoo Archives: gentoo-portage-dev

From: "W. Trevor King" <wking@×××××××.us>
To: gentoo-portage-dev@l.g.o
Subject: Re: [gentoo-portage-dev] [PATCH 3/3] pym/portage/package/ebuild/fetch.py: Factor out _get_uris
Date: Sun, 19 Jan 2014 23:06:34
Message-Id: 20140119230629.GV29063@odin.tremily.us
In Reply to: Re: [gentoo-portage-dev] [PATCH 3/3] pym/portage/package/ebuild/fetch.py: Factor out _get_uris by Alec Warner
1 On Sun, Jan 19, 2014 at 02:36:43PM -0800, Alec Warner wrote:
2 > On Sat, Jan 18, 2014 at 7:07 PM, W. Trevor King <wking@×××××××.us> wrote:
3 > > +def _get_file_uri_tuples(uris):
4 > > + """Return a list of (filename, uri) tuples
5 > > + """
6 > >
7 >
8 > As mike noted on another thread:
9 >
10 > ""Return a list of (filename, uri) tuples."""
11
12 I'd replaced this with:
13
14 """
15 Return a list of (filename, uri) tuples
16 """
17
18 in v2, but I'll queue the one-line form in v3.
19
20 > > +def _expand_mirror(uri, custom_mirrors=(), third_party_mirrors=()):
21 > > + """Replace the 'mirror://' scheme in the uri
22 > >
23 >
24 > Sentence should end in a period.
25
26 Ok. I'll do that for the other summaries as well, and uppercase URI,
27 in v3.
28
29 > > + writemsg(_("Invalid mirror definition in SRC_URI:\n"),
30 > > + noiselevel=-1)
31 > > + writemsg(" %s\n" % (uri), noiselevel=-1)
32 >
33 >
34 > Is this a py3k thing? You should be able to write:
35 >
36 > writemsg(" %s\n" % uri, noiselevel=-1)
37 >
38 > The tuple is only needed for multiple arguments in py2k.
39
40 1. I think I just copied and pasted it ;).
41 2. (uri) is not actually a tuple:
42
43 >>> type(('hello'))
44 <type 'str'>
45
46 To get a tuple, you need (uri,).
47
48 I'm fine removing the parens in v3.
49
50 > > +def _get_uris(uris, settings, custom_mirrors=(), locations=()):
51 > >
52 >
53 > I want you to be careful here. This is bad style when you are
54 > constructing mutable objects in parameter defaults:
55
56 I used tuples instead of lists because they are not mutable (as you
57 point out later on).
58
59 > I'm not sure if I appreciate that more or less than the other form....
60 >
61 > def _get_uris(uris, settings, custom_mirrors=None, locations=None):
62 > if not custom_mirrors:
63 > custom_mirrors = ()
64 > if not locations:
65 > locations = ()
66
67 If you want me to do it that way, I'll queue it for v3. I think the
68 default tuples are more readable. They are certainly shorter.
69
70 > Another advisable way to write it is to simply not have default
71 > arguments, and to force the caller to sync in an empty iterable:
72
73 Meh. I don't have strong feelings about this, but custom_mirrors
74 struck me as something that would not always be required ;).
75
76 > > + third_party_mirrors = settings.thirdpartymirrors()
77 > >
78 >
79 > Why pass in all of settings?
80
81 We need other stuff too, see v2. The less settings parsing I need to
82 do in fetch() itself, the happier I am. If that makes the helper
83 functions a bit uglier, that's fine. Fewer people will have to read
84 those.
85
86 > Think about testing this function.
87
88 Working on it for v3.
89
90 > Do you really want to try to construct some sort of 'testing'
91 > settings object, or simply construct a list?
92
93 I was going to use a dict for testing, and stub out a
94 thirdpartymirrors mock for _get_uris.
95 > > + third_party_mirror_uris = {}
96 > > + filedict = OrderedDict()
97 > > + primaryuri_dict = {}
98 > > + for filename, uri in _get_file_uri_tuples(uris=uris):
99 > > + if filename not in filedict:
100 > > + filedict[filename] = [
101 > > + os.path.join(location, 'distfiles',
102 > > filename)
103 > > + for location in locations]
104 > > + if uri is None:
105 > > + continue
106 > > + if uri.startswith('mirror://'):
107 > > + uris = _expand_mirror(
108 > >
109 >
110 > too many uri / uris variables...
111 >
112 > can we called this 'expanded_uris'?
113
114 Queued for v3.
115
116 > I'm really having trouble tracking what is what. Remember that
117 > 'uris' is already a parameter to this function. Are you shadowing it
118 > here, or trying to overwrite it?
119
120 Clobbering it. The original value is only used for the
121 _get_file_uri_tuples call.
122
123 > > + uri=uri, custom_mirrors=custom_mirrors,
124 > > + third_party_mirrors=third_party_mirrors)
125 > > + filedict[filename].extend(uri for group, uri in
126 > > uris)
127 > >
128 >
129 > group appears unused in your implicit iterable here.
130 >
131 > perhaps:
132 >
133 > filedict[filename].extend(uri for _, uri in uris)
134
135 Queued for v3.
136
137 > > + third_party_mirror_uris.setdefault(filename,
138 > > []).extend(
139 > > + uri for group, uri in uris
140 > > + if group == 'third-party')
141 > >
142 >
143 > I'm curious if this matters. We are iterator over 'uris' twice. Is it
144 > cheaper to do it once and build the iterables once?
145 >
146 > third_party_uris = []
147 > for group, uri in uris:
148 > if group == 'third_party':
149 > third_party_uris.append(uri)
150 > filedict[filename].append(uri)
151 >
152 > I'm guessing the iterable is so small it doesn't matter.
153
154 My guess is that the speed gain from list comprehension outweighs the
155 loss of double iterations, but I agree that it is probably doesn't
156 matter ;).
157
158 > > + if not filedict[filename]:
159 > > + writemsg(
160 > > + _("No known mirror by the name:
161 > > %s\n")
162 > > + % (mirror,))
163 > > + else:
164 > > + if restrict_fetch or force_mirror:
165 > >
166 >
167 > Are these globals or am I missing somethng?
168
169 Fixed in v2.
170
171
172 > > + # Only fetch from specific mirrors is
173 > > allowed.
174 > > + continue
175 > > + primaryuris = primaryuri_dict.get(filename)
176 > > + if primaryuris is None:
177 > > + primaryuris = []
178 > > + primaryuri_dict[filename] = primaryuris
179 > > + primaryuris.append(uri)
180 > > +
181 > > + # Order primaryuri_dict values to match that in SRC_URI.
182 > > + for uris in primaryuri_dict.values():
183 > > + uris.reverse()
184 >
185 > Is there any guaranteed ordering for dict.values()?
186
187 No.
188
189 > I thought dict order was random (and they seriously make it random
190 > in modern python versions, to detect bugs.) How does this
191 > uris.reverse() match the SRC_URI ordering?
192
193 No idea (copy-pasted code). I'd be happy to cut this out in v3.
194
195 > > +
196 > > + # Prefer third_party_mirrors over normal mirrors in cases when
197 > > + # the file does not yet exist on the normal mirrors.
198 > > + for filename, uris in third_party_mirror_uris.items():
199 > > + primaryuri_dict.setdefault(filename, []).extend(uris)
200 > > +
201 > > + # Now merge primaryuri values into filedict (includes mirrors
202 > > + # explicitly referenced in SRC_URI).
203 > > + if "primaryuri" in restrict:
204 > >
205 >
206 > same questoin here about where 'restrict' comes from.
207
208 Fixed in v2.
209
210 Thanks,
211 Trevor
212
213 --
214 This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
215 For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

Attachments

File name MIME type
signature.asc application/pgp-signature

Replies