Gentoo Archives: gentoo-commits

From: "André Erdmann" <dywi@×××××××.de>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/R_overlay:gsoc13/next commit in: roverlay/depres/simpledeprule/, roverlay/depres/
Date: Tue, 02 Jul 2013 21:09:34
Message-Id: 1372798730.bd91581d7a6cc12e2cfe9aa45a69ac5cdfdc6f67.dywi@gentoo
1 commit: bd91581d7a6cc12e2cfe9aa45a69ac5cdfdc6f67
2 Author: André Erdmann <dywi <AT> mailerd <DOT> de>
3 AuthorDate: Tue Jul 2 20:58:50 2013 +0000
4 Commit: André Erdmann <dywi <AT> mailerd <DOT> de>
5 CommitDate: Tue Jul 2 20:58:50 2013 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=bd91581d
7
8 roverlay/depres: configurable slot values
9
10 This commit (mainly) adds feature to FuzzySlotDependencyRule
11 * the relevant parts of a version string that make up the slot or subslot value
12 are configurable now
13 * slot rule modes: "open", "with version", "default"
14 * slot range restrict has been removed
15
16 ---
17 roverlay/depres/depenv.py | 16 ++
18 roverlay/depres/simpledeprule/rules.py | 339 +++++++++++++++++----------------
19 roverlay/depres/simpledeprule/util.py | 160 ++++++++++++++++
20 3 files changed, 350 insertions(+), 165 deletions(-)
21
22 diff --git a/roverlay/depres/depenv.py b/roverlay/depres/depenv.py
23 index 9371ef6..c298447 100644
24 --- a/roverlay/depres/depenv.py
25 +++ b/roverlay/depres/depenv.py
26 @@ -175,10 +175,26 @@ class DepEnv ( object ):
27 # "normalize"
28 vmod = '='
29
30 + version_strlist = version.split ( '.' )
31 + version_iparts = list()
32 +
33 + for v in version_strlist:
34 + #i = None
35 + try:
36 + i = int ( v )
37 + version_iparts.append ( i )
38 + except ValueError:
39 + v2 = v.partition ( '_' )[0].partition ( '-' ) [0]
40 + version_iparts.append ( int ( v2 ) if v2 else 0 )
41 +
42 +
43 +
44 result.append ( dict (
45 name = m.group ( 'name' ),
46 version_modifier = vmod,
47 version = version,
48 + version_strlist = version_strlist,
49 + version_tuple = tuple ( version_iparts ),
50 vmod = self.VMOD.get ( vmod, self.VMOD_UNDEF ),
51 ) )
52
53
54 diff --git a/roverlay/depres/simpledeprule/rules.py b/roverlay/depres/simpledeprule/rules.py
55 index ac3fa89..999a8b4 100644
56 --- a/roverlay/depres/simpledeprule/rules.py
57 +++ b/roverlay/depres/simpledeprule/rules.py
58 @@ -20,88 +20,15 @@ __all__ = (
59 'SimpleFuzzyDependencyRule', 'SimpleFuzzyIgnoreDependencyRule'
60 )
61
62 -from roverlay.depres.simpledeprule.abstractrules import \
63 - SimpleRule, FuzzySimpleRule
64 -
65 -class SlotRestrict ( object ):
66 - def accepts ( self, k ):
67 - """Returns True if k is allowed, else False.
68
69 - arguments:
70 - * k -- int
71 - """
72 - return True
73 +from roverlay.depres.simpledeprule.util import \
74 + RuleFileSyntaxError, get_slot_restrict, get_slot_parser
75
76 - def __bool__ ( self ):
77 - return True
78 -
79 - def noexport ( self ):
80 - pass
81 -
82 - def __str__ ( self ):
83 - return ':'
84 -# --- end of SlotRestrict ---
85 -
86 -class SlotRangeRestrict ( SlotRestrict ):
87 - DEFAULT_LOW = 0
88 - DEFAULT_HIGH = 1000
89 -
90 - def __init__ ( self, low, high ):
91 - super ( SlotRangeRestrict, self ).__init__()
92 - if low:
93 - self.low = int ( low )
94 - else:
95 - self.low = self.DEFAULT_LOW
96 - self._implicit_low = True
97 -
98 - if high:
99 - self.high = int ( high )
100 - else:
101 - self.high = self.DEFAULT_HIGH
102 - self._implicit_high = True
103 - # --- end of __init__ (...) ---
104 -
105 - def noexport ( self ):
106 - if hasattr ( self, '_implicit_low' ):
107 - del self._implicit_low
108 - if hasattr ( self, '_implicit_high' ):
109 - del self._implicit_high
110 - # --- end of noexport (...) ---
111 -
112 - def accepts ( self, k ):
113 - """Returns True if k is allowed, else False.
114 -
115 - arguments:
116 - * k -- int
117 - """
118 - return k >= self.low and k <= self.high
119 -
120 - def __str__ ( self ):
121 - return ":{low}..{high}".format (
122 - low = ( '' if hasattr ( self, '_implicit_low' ) else self.low ),
123 - high = ( '' if hasattr ( self, '_implicit_high' ) else self.high ),
124 - )
125 - # --- end of __str__ (...) ---
126 -
127 -# --- end of SlotRangeRestrict ---
128 -
129 -class SlotSetRestrict ( SlotRestrict ):
130 - def __init__ ( self, iterable ):
131 - self._iset = frozenset ( int ( k ) for k in iterable )
132 -
133 - def accepts ( self, k ):
134 - """Returns True if k is allowed, else False.
135 +from roverlay.depres.simpledeprule.abstractrules import \
136 + SimpleRule, FuzzySimpleRule
137
138 - arguments:
139 - * k -- int
140 - """
141 - return k in self._iset
142
143 - def __str__ ( self ):
144 - return ':' + ','.join ( str ( k ) for k in sorted ( self._iset ) )
145 - # --- end of __str__ (...) ---
146
147 -# --- end of SlotSetRestrict ---
148
149 class RuleConstructor ( object ):
150
151 @@ -123,61 +50,85 @@ class RuleConstructor ( object ):
152 return ( SimpleFuzzyIgnoreDependencyRule, get_kwless(), {} )
153 elif kw == self.kw_fuzzy:
154 ## syntax
155 - ## ~cat/pkg:<slot range>:<slot suffix>
156 - kwless = get_kwless()
157 - resolving, sepa, remainder = kwless.partition ( ':' )
158 -
159 - if sepa:
160 - # fuzzy slot rule
161 + ## ~<cat>/<pkg>[:[<slot option>]]*
162 + ## where slot option is any of
163 + ## * slot restrict (range, list)
164 + ## * "with version", "open" ("*" and "=" slot operators)
165 + ## * relevant version parts ("1.2.3.4" => "1" if 1, "1.2" if 2, ...)
166 + ## * relevant subslot version parts ("1.2.3.4" => <SLOT>/<SUBSLOT?>)
167 + ## * slot operator ("=")
168 +
169 + kwless = get_kwless()
170 + line_components = kwless.split ( ':' )
171 +
172 + if len ( line_components ) < 2:
173 + # non-slot fuzzy rule
174 + return ( SimpleFuzzyDependencyRule, kwless, {} )
175 + else:
176 kwargs = dict()
177 - slot_head, slot_sepa, slot_rem = remainder.partition ( ':' )
178 -
179 - if slot_sepa:
180 - # int range restriction
181 - istart, isepa, istop = slot_head.partition ( '..' )
182 - if isepa:
183 - kwargs ['slot_restrict'] = SlotRangeRestrict (
184 - low=istart, high=istop
185 - )
186 - else:
187 - # int list restriction
188 + lc_iter = iter ( line_components )
189 + # drop first item as it's the resolving string and not an option
190 + next ( lc_iter )
191 + for opt_str in lc_iter:
192 + opt, has_value, value = opt_str.partition ( '=' )
193
194 - # "filter(None,...)" filters 0 but not '0'
195 - istr_list = list (
196 - filter ( None, slot_head.split ( ',' ) )
197 - #filter ( lambda s : s or s == 0, slot_head.split ( ',' ) )
198 - )
199 + if not opt_str:
200 + # empty
201 + pass
202 + elif opt == 'default':
203 + kwargs ['slot_mode'] = 0
204
205 - if istr_list:
206 - kwargs ['slot_restrict'] = SlotSetRestrict ( istr_list )
207 + elif opt == 'with_version' or opt == '+v':
208 + kwargs ['slot_mode'] = 1
209
210 - remainder = slot_rem
211 - else:
212 - #kwargs ['slot_restrict'] = SlotRestrict()
213 - remainder = slot_head
214 - # -- end if;
215 -
216 - if remainder[:2] == '+v':
217 - kwargs ['with_version'] = True
218 - remainder = remainder[2:]
219 - # -- end if;
220 -
221 - if not remainder:
222 - pass
223 - elif remainder[0] in { '/', '*', '=' }:
224 - # subslot, "any slot" operators
225 - # (subslots don't seem to make much sense here)
226 -
227 - ##if self.eapi < 5: raise ...
228 - kwargs ['slot_suffix'] = remainder
229 + elif opt == 'open':
230 + kwargs ['slot_mode'] = 2
231 +
232 + elif ( opt == 'restrict' or opt == 'r' ) and value:
233 + kwargs ['slot_restrict'] = get_slot_restrict ( value )
234 +
235 + elif ( opt == 'slotparts' or opt == 's' ) and value:
236 + kwargs ['slotparts'] = get_slot_parser ( value )
237 +
238 + elif ( opt == 'subslotparts' or opt == '/' ) and value:
239 + kwargs ['subslotparts'] = get_slot_parser ( value )
240 +
241 + elif opt_str[0] == '/' and not has_value:
242 + kwargs ['subslotparts'] = get_slot_parser ( opt_str[1:] )
243 +
244 +# elif opt == 'operator' and value:
245 +# # unsafe, could be used to inject "$(rm -rf /)" etc.
246 +# kwargs ['slot_operator'] = value
247 +
248 + elif opt == '*':
249 + kwargs ['slot_operator'] = '*'
250 +
251 + elif not opt and has_value:
252 + # "="
253 + kwargs ['slot_operator'] = '='
254 + pass
255 +
256 + else:
257 + raise RuleFileSyntaxError (
258 + "cannot parse option {!r} from {!r}".format (
259 + opt_str, kwless
260 + )
261 + )
262 + # -- end for lc_iter
263 +
264 + if (
265 + kwargs.get ( 'slot_operator' ) == '*'
266 + and kwargs.get ( 'slot_mode' ) != 2
267 + ):
268 + raise RuleFileSyntaxError (
269 + "The '*' slot operator needs an 'open' rule."
270 + )
271 else:
272 - raise Exception (
273 - "unknown slot rule remainder {!r}".format ( remainder )
274 + return (
275 + SimpleFuzzySlotDependencyRule, line_components[0], kwargs
276 )
277 + # -- end if line_components
278
279 - return ( SimpleFuzzySlotDependencyRule, resolving, kwargs )
280 - else:
281 - return ( SimpleFuzzyDependencyRule, kwless, {} )
282 else:
283 return ( SimpleDependencyRule, keyworded_str, {} )
284 # --- end of lookup (...) ---
285 @@ -295,9 +246,11 @@ class SimpleFuzzySlotDependencyRule ( FuzzySimpleRule ):
286 def __init__ ( self,
287 priority = 71,
288 resolving_package = None,
289 - slot_suffix = None,
290 + slot_mode = None,
291 slot_restrict = None,
292 - with_version = False,
293 + slotparts = None,
294 + subslotparts = None,
295 + slot_operator = None,
296 **kw
297 ):
298 super ( SimpleFuzzySlotDependencyRule, self ) . __init__ (
299 @@ -307,39 +260,93 @@ class SimpleFuzzySlotDependencyRule ( FuzzySimpleRule ):
300 **kw
301 )
302
303 - self.slot_suffix = slot_suffix
304 + self.mode = 0 if slot_mode is None else slot_mode
305 self.slot_restrict = slot_restrict
306 -
307 - if with_version:
308 + self.slot_operator = slot_operator
309 + self.slotparts = get_slot_parser ("0") if slotparts is None else slotparts
310 + self.subslotparts = subslotparts
311 +
312 + if self.mode == 0:
313 + # "default"
314 + self._resolving_fmt = self.resolving_package + ':{slot}'
315 + if self.slot_operator:
316 + self._resolving_fmt += self.slot_operator
317 +
318 + elif self.mode == 1:
319 + # "with version"
320 self._resolving_fmt = (
321 '{vmod}' + self.resolving_package + '-{version}:{slot}'
322 - + ( slot_suffix or '' )
323 )
324 - self.with_version = True
325 + if self.slot_operator:
326 + self._resolving_fmt += self.slot_operator
327 +
328 + elif self.mode == 2:
329 + # "open" slot
330 + if not self.slot_operator:
331 + self.slot_operator = '='
332 +
333 + del self.slot_restrict
334 +
335 + self._orig_resolving_package = self.resolving_package
336 + self.resolving_package += ':' + self.slot_operator
337 else:
338 - self._resolving_fmt = (
339 - self.resolving_package + ':{slot}' + ( slot_suffix or '' )
340 + raise Exception (
341 + "unknown fuzzy slot rule mode {}".format ( self.mode )
342 )
343 - self.with_version = False
344 +
345 +
346
347 if self.is_selfdep:
348 raise NotImplementedError ( "fuzzy slot rule must not be a selfdep." )
349 # --- end of __init__ (...) ---
350
351 def noexport ( self ):
352 - del self.slot_suffix
353 - del self.with_version
354 + del self.slot_operator
355 + del self.mode
356 if self.slot_restrict:
357 self.slot_restrict.noexport()
358 # --- end of noexport (...) ---
359
360 def get_resolving_str ( self ):
361 - return "{prefix}{resolv}{restrict}:{flags}{slot}".format (
362 - prefix = self.RULE_PREFIX,
363 - resolv = self.resolving_package,
364 - restrict = ( self.slot_restrict or '' ),
365 - flags = ( '+v' if self.with_version else '' ),
366 - slot = ( self.slot_suffix or '' ),
367 + ## syntax
368 + ## ~<cat>/<pkg>[:[<slot option>]]*
369 + ## where slot option is any of
370 + ## * slot restrict (range, list)
371 + ## * "with version", "open" ("*" and "=" slot operators)
372 + ## * relevant version parts ("1.2.3.4" => "1" if 1, "1.2" if 2, ...)
373 + ## * relevant subslot version parts ("1.2.3.4" => <SLOT>/<SUBSLOT?>)
374 + ## * slot operator ("=")
375 +
376 + def gen_opts():
377 + if self.mode == 2:
378 + yield "open"
379 + else:
380 + if self.mode == 1:
381 + yield "with_version"
382 +
383 + if self.slot_restrict:
384 + yield "restrict=" + str ( self.slot_restrict )
385 +
386 + if self.slotparts and (
387 + not hasattr ( self.slotparts, '_index' )
388 + or self.slotparts._index != 0
389 + ):
390 + yield "s=" + str ( self.slotparts )
391 +
392 + if self.subslotparts:
393 + yield "/" + str ( self.subslotparts )
394 + # -- end if
395 + if self.slot_operator:
396 + yield self.slot_operator
397 +
398 + return "{prefix}{resolv}:{opts}".format (
399 + prefix = self.RULE_PREFIX,
400 + resolv = (
401 + self._orig_resolving_package
402 + if hasattr ( self, '_orig_resolving_package' )
403 + else self.resolving_package,
404 + ),
405 + opts = ':'.join ( gen_opts() )
406 )
407 # --- end of get_resolving_str (...) ---
408
409 @@ -350,28 +357,30 @@ class SimpleFuzzySlotDependencyRule ( FuzzySimpleRule ):
410 if not ( vmod & dep_env.VMOD_NOT ):
411 # can be resolved as slot(ted) dep
412
413 - ver_str = fuzzy ['version']
414 - v_major, sepa, v_remainder = ver_str.partition ( '.' )
415 - try:
416 - # TODO/FIXME: slot != int(v_major);
417 - # example: sci-libs/fftw where slots are K.J (2.1, 3.0)
418 - slot = int ( v_major )
419 -
420 - # resolve '<' and '>' by decrementing/incrementing slot
421 - if vmod == dep_env.VMOD_LT:
422 - slot -= 1
423 - elif vmod == dep_env.VMOD_GT:
424 - slot += 1
425 -
426 - if not self.slot_restrict or self.slot_restrict.accepts ( slot ):
427 - res = self._resolving_fmt.format (
428 - slot=slot,
429 - version=ver_str,
430 - vmod=fuzzy ['version_modifier'],
431 - )
432 - except ValueError:
433 - pass
434 - # -- end if vmod
435 + if self.mode == 2:
436 + res = self._resolving_str
437 + elif vmod & dep_env.VMOD_EQ:
438 + slot_str = None
439 + slot = self.slotparts.get_slot ( fuzzy )
440 +
441 + if slot is not None:
442 + if self.subslotparts:
443 + subslot = self.subslotparts.get_slot ( fuzzy )
444 + if subslot is not None:
445 + slot_str = slot + '/' + subslot
446 + else:
447 + slot_str = slot
448 +
449 + if slot_str and (
450 + not self.slot_restrict
451 + or self.slot_restrict.accepts ( slot )
452 + ):
453 + res = self._resolving_fmt.format (
454 + slot=slot_str,
455 + version=fuzzy['version'], vmod=fuzzy['version_modifier']
456 + )
457 +
458 + # -- end if vmod != NOT
459
460 return res
461 # --- end of handle_version_relative_match (...) ---
462
463 diff --git a/roverlay/depres/simpledeprule/util.py b/roverlay/depres/simpledeprule/util.py
464 new file mode 100644
465 index 0000000..0a8311c
466 --- /dev/null
467 +++ b/roverlay/depres/simpledeprule/util.py
468 @@ -0,0 +1,160 @@
469 +# R overlay -- simple dependency rules
470 +# -*- coding: utf-8 -*-
471 +# Copyright (C) 2013 André Erdmann <dywi@×××××××.de>
472 +# Distributed under the terms of the GNU General Public License;
473 +# either version 2 of the License, or (at your option) any later version.
474 +
475 +
476 +class RuleFileSyntaxError ( Exception ):
477 + pass
478 +
479 +
480 +def get_int_range_or_list (
481 + value_str, default_low=0, default_high=1000, list_sepa=','
482 +):
483 + low, sepa, high = value_str.partition ( '..' )
484 + if sepa:
485 + i_low = int ( low ) if low else default_low
486 + i_high = (
487 + int ( high ) if high else (
488 + i_low if default_high is True else default_high
489 + )
490 + )
491 + return ( True, i_low, i_high )
492 + else:
493 + return ( False,
494 + tuple ( int ( k ) for k in value_str.split ( list_sepa ) )
495 + )
496 +# --- end get_int_range_or_list (...) ---
497 +
498 +
499 +
500 +class SlotRestrict ( object ):
501 + def accepts ( self, k ):
502 + """Returns True if k is allowed, else False.
503 +
504 + arguments:
505 + * k -- int
506 + """
507 + return True
508 +
509 + def __bool__ ( self ):
510 + return True
511 +
512 + def noexport ( self ):
513 + pass
514 +
515 + def __str__ ( self ):
516 + return ''
517 +# --- end of SlotRestrict ---
518 +
519 +class SlotSetRestrict ( SlotRestrict ):
520 + def __init__ ( self, iterable ):
521 + self._slotset = frozenset ( iterable )
522 +
523 + def accepts ( self, k ):
524 + """Returns True if k is allowed, else False.
525 +
526 + arguments:
527 + * k -- slot (str)
528 + """
529 + return k in self._slotset
530 +
531 + def __str__ ( self ):
532 + return ','.join ( sorted ( self._slotset ) )
533 + # --- end of __str__ (...) ---
534 +
535 +# --- end of SlotSetRestrict ---
536 +
537 +class SlotValueCreatorBase ( object ):
538 +
539 + def get_slot ( self, *args, **kwargs ):
540 + raise NotImplementedError()
541 + # --- end of get_slot (...) ---
542 +
543 + def __str__ ( self ):
544 + raise NotImplementedError()
545 + # --- end of __str__ (...) ---
546 +
547 +
548 +class ImmediateSlotValueCreator ( SlotValueCreatorBase ):
549 + def __init__ ( self, v_str ):
550 + super ( ImmediateSlotValueCreator, self ).__init__()
551 + self._value = v_str
552 + # --- end of __init__ (...) ---
553 +
554 + def get_slot ( self, *args, **kwargs ):
555 + return self._value
556 + # --- end of get_slot (...) ---
557 +
558 + def __str__ ( self ):
559 + return "i" + self._value
560 +
561 +class SingleIndexValueCreator ( SlotValueCreatorBase ):
562 + def __init__ ( self, index ):
563 + super ( SingleIndexValueCreator, self ).__init__()
564 + self._index = index
565 + # --- end of __init__ (...) ---
566 +
567 + def get_slot ( self, fuzzy ):
568 + version_components = fuzzy ['version_strlist']
569 + if len ( version_components ) > self._index:
570 + return version_components [self._index]
571 + else:
572 + return None
573 + # --- end of get_slot (...) ---
574 +
575 + def __str__ ( self ):
576 + return str ( self._index )
577 +
578 +
579 +class IndexRangeSlotValueCreator ( SlotValueCreatorBase ):
580 + def __init__ ( self, low, high ):
581 + super ( IndexRangeSlotValueCreator, self ).__init__()
582 + self._low = low
583 + self._high = high + 1 if high >= 0 else high
584 +
585 + def get_slot ( self, fuzzy ):
586 + # if self._low > self._high
587 + # if self._high < 0: -- dont care
588 + version_components = fuzzy ['version_strlist']
589 + if len ( version_components ) >= self._high:
590 + return '.'.join ( version_components [self._low:self._high] )
591 + else:
592 + return None
593 + # --- end of get_slot (...) ---
594 +
595 + def __str__ ( self ):
596 + return str ( self._low ) + '..' + str (
597 + ( self._high - 1 ) if self._high > 0 else self._high
598 + )
599 +
600 +
601 +def get_slot_parser ( vstr ):
602 + if vstr [0] == 'i':
603 + # "immediate" value
604 + s = vstr [1:]
605 + return ImmediateSlotValueCreator ( v_str=s )
606 + else:
607 + range_or_list = get_int_range_or_list ( vstr, default_high=True )
608 + if range_or_list [0]:
609 + if range_or_list[1] == range_or_list[2]:
610 + return SingleIndexValueCreator ( index=range_or_list[1] )
611 + else:
612 + return IndexRangeSlotValueCreator (
613 + low=range_or_list[1], high=range_or_list[2]
614 + )
615 + elif len ( range_or_list[1] ) < 2:
616 + return SingleIndexValueCreator ( index=range_or_list[1][0] )
617 + else:
618 + raise RuleFileSyntaxError (
619 + "slot part selection must not be a list"
620 + )
621 +# --- end of get_slot_parser (...) ---
622 +
623 +def get_slot_restrict ( vstr ):
624 + if vstr:
625 + return SlotSetRestrict ( vstr.split ( ',' ) )
626 + else:
627 + return None
628 +# --- end of get_slot_restrict (...) --