1 |
commit: f4fe2f55298624cd522b554aa57b505591a4138a |
2 |
Author: André Erdmann <dywi <AT> mailerd <DOT> de> |
3 |
AuthorDate: Fri Jun 29 22:36:33 2012 +0000 |
4 |
Commit: André Erdmann <dywi <AT> mailerd <DOT> de> |
5 |
CommitDate: Fri Jun 29 22:36:33 2012 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=f4fe2f55 |
7 |
|
8 |
dependency resolution: 'fuzzy' rules |
9 |
|
10 |
These extended simple rules match various dependency strings |
11 |
with a single rule, e.g. a fuzzy "R" rule matches |
12 |
"R (>= 2.10)" as ">=dev-lang/R-2.10" and "R <2.15" as "<dev-lang/R-2.15". |
13 |
|
14 |
Also added easier syntax for R package dependencies (sound -> sci-R/sound) |
15 |
in the dep rule file(s), which can now be written as 'sound' instead of |
16 |
a category-hardcoded 'sci-R/sound :: sound' statement. |
17 |
|
18 |
new file: roverlay/depres/abstractsimpledeprule.py |
19 |
modified: roverlay/depres/deprule.py |
20 |
modified: roverlay/depres/simpledeprule.py |
21 |
|
22 |
--- |
23 |
roverlay/depres/abstractsimpledeprule.py | 204 ++++++++++++++++++++++++ |
24 |
roverlay/depres/deprule.py | 11 +- |
25 |
roverlay/depres/simpledeprule.py | 254 ++++++++++++++---------------- |
26 |
3 files changed, 325 insertions(+), 144 deletions(-) |
27 |
|
28 |
diff --git a/roverlay/depres/abstractsimpledeprule.py b/roverlay/depres/abstractsimpledeprule.py |
29 |
new file mode 100644 |
30 |
index 0000000..b03ce63 |
31 |
--- /dev/null |
32 |
+++ b/roverlay/depres/abstractsimpledeprule.py |
33 |
@@ -0,0 +1,204 @@ |
34 |
+import logging |
35 |
+ |
36 |
+from roverlay.depres import deprule |
37 |
+ |
38 |
+TMP_LOGGER = logging.getLogger ('simpledeps') |
39 |
+ |
40 |
+class SimpleRule ( deprule.DependencyRule ): |
41 |
+ """A dependency rule that represents an ignored package in portage.""" |
42 |
+ |
43 |
+ def __init__ ( self, |
44 |
+ dep_str=None, priority=50, resolving_package=None, |
45 |
+ logger_name='simple_rule' |
46 |
+ ): |
47 |
+ """Initializes a SimpleIgnoreDependencyRule. |
48 |
+ |
49 |
+ arguments: |
50 |
+ * dep_str -- a dependency string that this rule is able to resolve |
51 |
+ * priority -- priority of this rule |
52 |
+ """ |
53 |
+ super ( SimpleRule, self ) . __init__ ( priority ) |
54 |
+ self.dep_alias = list() |
55 |
+ |
56 |
+ self.logger = TMP_LOGGER.getChild ( logger_name ) |
57 |
+ |
58 |
+ self.resolving_package = resolving_package |
59 |
+ |
60 |
+ self.prepare_lowercase_alias = True |
61 |
+ |
62 |
+ if not dep_str is None: |
63 |
+ self.dep_alias.append ( dep_str ) |
64 |
+ |
65 |
+ self.logger.debug ( "new rule (%s) for %s" % ( self.__class__.__name__, self.resolving_package ) ) |
66 |
+ |
67 |
+ # --- end of __init__ (...) --- |
68 |
+ |
69 |
+ def done_reading ( self ): |
70 |
+ self.dep_alias = frozenset ( self.dep_alias ) |
71 |
+ if self.prepare_lowercase_alias: |
72 |
+ self.dep_alias_low = frozenset ( x.lower() for x in self.dep_alias ) |
73 |
+ |
74 |
+ def add_resolved ( self, dep_str ): |
75 |
+ """Adds an dependency string that should be matched by this rule. |
76 |
+ |
77 |
+ arguments: |
78 |
+ * dep_str -- |
79 |
+ """ |
80 |
+ self.dep_alias.append ( dep_str ) |
81 |
+ # --- end of add_resolved (...) --- |
82 |
+ |
83 |
+ def _find ( self, dep_str, lowercase ): |
84 |
+ if lowercase: |
85 |
+ if hasattr ( self, 'dep_alias_low' ): |
86 |
+ if dep_str in self.dep_alias_low: |
87 |
+ return True |
88 |
+ else: |
89 |
+ if dep_str in ( alias.lower() for alias in self.dep_alias ): |
90 |
+ return True |
91 |
+ |
92 |
+ return dep_str in self.dep_alias |
93 |
+ # --- end of _find (...) --- |
94 |
+ |
95 |
+ def matches ( self, dep_env, lowercase=True ): |
96 |
+ """Returns True if this rule matches the given DepEnv, else False. |
97 |
+ |
98 |
+ arguments: |
99 |
+ * dep_env -- |
100 |
+ * lowercase -- if True: be case-insensitive when iterating over all |
101 |
+ stored dep_strings |
102 |
+ """ |
103 |
+ |
104 |
+ if self._find ( |
105 |
+ dep_env.dep_str_low if lowercase else dep_env.dep_str, lowercase |
106 |
+ ): |
107 |
+ self.logger.debug ( |
108 |
+ "matches %s with score %i and priority %i." |
109 |
+ % ( dep_env.dep_str, self.max_score, self.priority ) |
110 |
+ ) |
111 |
+ return ( self.max_score, self.resolving_package ) |
112 |
+ |
113 |
+ return None |
114 |
+ # --- end of matches (...) --- |
115 |
+ |
116 |
+ def export_rule ( self, resolving_to=None ): |
117 |
+ """Returns this rule as a list of text lines that can be written into |
118 |
+ a file. |
119 |
+ An empty list will be returned if dep_alias has zero length. |
120 |
+ |
121 |
+ arguments: |
122 |
+ * resolving_to -- portage package that the exported rule should |
123 |
+ resolve to, defaults to self.resolving_package or |
124 |
+ an ignore keyword such as '!'. |
125 |
+ """ |
126 |
+ |
127 |
+ alias_count = len ( self.dep_alias ) |
128 |
+ |
129 |
+ retlist = [] |
130 |
+ |
131 |
+ if alias_count: |
132 |
+ if resolving_to is None: |
133 |
+ if hasattr ( self, 'resolving_package'): |
134 |
+ resolving_package = self.resolving_package |
135 |
+ else: |
136 |
+ resolving_package = '!' |
137 |
+ else: |
138 |
+ resolving_package = resolving_to |
139 |
+ |
140 |
+ # todo hardcoded rule format here |
141 |
+ if alias_count > 1: |
142 |
+ |
143 |
+ retlist = [ resolving_package + ' {\n' ] + \ |
144 |
+ [ "\t%s\n" % alias for alias in self.dep_alias ] + \ |
145 |
+ [ '}\n' ] |
146 |
+ else: |
147 |
+ retlist = [ |
148 |
+ "%s :: %s\n" % ( resolving_package, self.dep_alias [0] ) |
149 |
+ ] |
150 |
+ |
151 |
+ # -- if |
152 |
+ |
153 |
+ return retlist |
154 |
+ # --- end of export_rule (...) --- |
155 |
+ |
156 |
+class FuzzySimpleRule ( SimpleRule ): |
157 |
+ |
158 |
+ def __init__ ( self, *args, **kw ): |
159 |
+ super ( FuzzySimpleRule, self ) . __init__ ( *args, **kw ) |
160 |
+ self.prepare_lowercase_alias = True |
161 |
+ |
162 |
+ # 0 : version with modifier, 1 : version w/o mod, 2 : name only, 3 : std |
163 |
+ self.fuzzy_score = ( 1250, 1000, 750, 500 ) |
164 |
+ self.max_score = max ( self.fuzzy_score ) |
165 |
+ |
166 |
+ def matches ( self, dep_env ): |
167 |
+ if self._find ( dep_env.dep_str_low, lowercase=True ): |
168 |
+ # non-fuzzy match |
169 |
+ self.logger.debug ( |
170 |
+ "matches %s with score %i and priority %i." |
171 |
+ % ( dep_env.dep_str, self.max_score, self.priority ) |
172 |
+ ) |
173 |
+ return ( self.fuzzy_score[3], self.resolving_package ) |
174 |
+ |
175 |
+ elif hasattr ( dep_env, 'fuzzy' ): |
176 |
+ for fuzzy in dep_env.fuzzy: |
177 |
+ if 'name' in fuzzy: |
178 |
+ if self._find ( fuzzy ['name'], lowercase=True ): |
179 |
+ # fuzzy match found |
180 |
+ |
181 |
+ if self.resolving_package is None: |
182 |
+ # ignore rule |
183 |
+ res = None |
184 |
+ score = self.fuzzy_score [2] |
185 |
+ |
186 |
+ |
187 |
+ elif 'version' in fuzzy: |
188 |
+ |
189 |
+ ver_pkg = '-'.join ( ( |
190 |
+ self.resolving_package, fuzzy ['version'] |
191 |
+ ) ) |
192 |
+ |
193 |
+ if 'version_modifier' in fuzzy: |
194 |
+ vmod = fuzzy ['version_modifier'] |
195 |
+ if '!' in vmod: |
196 |
+ # package matches, but specific version is forbidden |
197 |
+ # ( !<package>-<specific verion> <package> ) |
198 |
+ res = '( !=%s %s )' % ( |
199 |
+ ver_pkg, |
200 |
+ self.resolving_package |
201 |
+ ) |
202 |
+ |
203 |
+ else: |
204 |
+ # std vmod: >=, <=, =, <, > |
205 |
+ res = vmod + ver_pkg |
206 |
+ |
207 |
+ score = self.fuzzy_score[0] |
208 |
+ |
209 |
+ else: |
210 |
+ # version required, but no modifier: defaults to '>=' |
211 |
+ |
212 |
+ res = '>=' + ver_pkg |
213 |
+ score = self.fuzzy_score[1] |
214 |
+ |
215 |
+ else: |
216 |
+ # substring match |
217 |
+ # currently not possible (see DepEnv's regexes) |
218 |
+ score = fuzzy[2] |
219 |
+ res = self.resolving_package |
220 |
+ # --- if resolving... elif version ... else |
221 |
+ |
222 |
+ |
223 |
+ self.logger.debug ( |
224 |
+ "fuzzy-match: %s resolved as '%s' with score=%i." |
225 |
+ % ( dep_env.dep_str, res, score ) |
226 |
+ ) |
227 |
+ return ( score, res ) |
228 |
+ # --- if find (=match found) |
229 |
+ # --- if name in |
230 |
+ # --- for fuzzy |
231 |
+ # --- elif hasattr |
232 |
+ |
233 |
+ return None |
234 |
+ # --- end of matches (...) --- |
235 |
+ |
236 |
+ |
237 |
+ |
238 |
|
239 |
diff --git a/roverlay/depres/deprule.py b/roverlay/depres/deprule.py |
240 |
index b02213c..72e706d 100644 |
241 |
--- a/roverlay/depres/deprule.py |
242 |
+++ b/roverlay/depres/deprule.py |
243 |
@@ -16,8 +16,9 @@ class DependencyRule ( object ): |
244 |
# --- end of __init__ (...) --- |
245 |
|
246 |
def matches ( self, dep_env ): |
247 |
- """Returns an int > 0 if this rule matches the given DepEnv.""" |
248 |
- return 0 |
249 |
+ """Returns a tuple ( score ::= int > 0, matching dep ::= str ) |
250 |
+ if this rule matches the given DepEnv, else None""" |
251 |
+ return None |
252 |
# --- end of matches (...) --- |
253 |
|
254 |
# --- end of DependencyRule --- |
255 |
@@ -97,12 +98,12 @@ class DependencyRulePool ( object ): |
256 |
order.reverse() |
257 |
|
258 |
for index in order: |
259 |
- score = self.rules [index].matches ( dep_env ) |
260 |
- if score: |
261 |
+ result = self.rules [index].matches ( dep_env ) |
262 |
+ if result is not None and result [0] > 0: |
263 |
if skipped < skip_matches: |
264 |
skipped += 1 |
265 |
else: |
266 |
- return ( score, self.rules [index].get_dep () ) |
267 |
+ return result |
268 |
|
269 |
|
270 |
return None |
271 |
|
272 |
diff --git a/roverlay/depres/simpledeprule.py b/roverlay/depres/simpledeprule.py |
273 |
index ee40045..ce4ba10 100644 |
274 |
--- a/roverlay/depres/simpledeprule.py |
275 |
+++ b/roverlay/depres/simpledeprule.py |
276 |
@@ -5,122 +5,23 @@ |
277 |
import re |
278 |
import logging |
279 |
|
280 |
+from roverlay import config |
281 |
from roverlay.depres import deprule |
282 |
+from roverlay.depres.abstractsimpledeprule import SimpleRule, FuzzySimpleRule |
283 |
|
284 |
TMP_LOGGER = logging.getLogger ('simpledeps') |
285 |
|
286 |
-class SimpleIgnoreDependencyRule ( deprule.DependencyRule ): |
287 |
- """A dependency rule that represents an ignored package in portage.""" |
288 |
- |
289 |
- def __init__ ( self, dep_str=None, priority=50 ): |
290 |
- """Initializes a SimpleIgnoreDependencyRule. |
291 |
- |
292 |
- arguments: |
293 |
- * dep_str -- a dependency string that this rule is able to resolve |
294 |
- * priority -- priority of this rule |
295 |
- """ |
296 |
- super ( SimpleIgnoreDependencyRule, self ) . __init__ ( priority ) |
297 |
- self.dep_alias = set () |
298 |
- |
299 |
- self.logger = TMP_LOGGER.getChild ( 'IGNORE_DEPS' ) |
300 |
- |
301 |
- if not dep_str is None: |
302 |
- self.dep_alias.add ( dep_str ) |
303 |
- |
304 |
- # --- end of __init__ (...) --- |
305 |
- |
306 |
- def add_resolved ( self, dep_str ): |
307 |
- """Adds an dependency string that should be matched by this rule. |
308 |
- |
309 |
- arguments: |
310 |
- * dep_str -- |
311 |
- """ |
312 |
- self.dep_alias.add ( dep_str ) |
313 |
- # --- end of add_resolved (...) --- |
314 |
- |
315 |
- def matches ( self, dep_env, lowercase=True ): |
316 |
- """Returns True if this rule matches the given DepEnv, else False. |
317 |
- |
318 |
- arguments: |
319 |
- * dep_env -- |
320 |
- * lowercase -- if True: be case-insensitive when iterating over all |
321 |
- stored dep_strings |
322 |
- """ |
323 |
- |
324 |
- def logmatch ( score=self.max_score ): |
325 |
- """Wrapper function that logs a successful match and |
326 |
- returns its score. |
327 |
- |
328 |
- arguments: |
329 |
- * score -- score of this match, defaults to self.max_score |
330 |
- """ |
331 |
- |
332 |
- self.logger.debug ( "matches %s with score %i and priority %i." % |
333 |
- ( dep_env.dep_str, score, self.priority ) |
334 |
- ) |
335 |
- return score |
336 |
- # --- end of logmatch (...) --- |
337 |
- |
338 |
- if lowercase: |
339 |
- #lower_dep_str = dep_env.dep_str.lower() |
340 |
- for alias in self.dep_alias: |
341 |
- if alias.lower() == dep_env.dep_str_low: |
342 |
- return logmatch () |
343 |
- elif dep_env.dep_str in self.dep_alias: |
344 |
- return logmatch () |
345 |
- |
346 |
- return 0 |
347 |
- # --- end of matches (...) --- |
348 |
- |
349 |
- def get_dep ( self ): |
350 |
- """Returns the textual portage package representation of this rule, |
351 |
- which is None 'cause this is an ignored dependency. |
352 |
- """ |
353 |
- return None |
354 |
- # --- end of get_dep (...) --- |
355 |
- |
356 |
- def export_rule ( self, resolving_to=None ): |
357 |
- """Returns this rule as a list of text lines that can be written into |
358 |
- a file. |
359 |
- An empty list will be returned if dep_alias has zero length. |
360 |
- |
361 |
- arguments: |
362 |
- * resolving_to -- portage package that the exported rule should |
363 |
- resolve to, defaults to self.resolving_package or |
364 |
- an ignore keyword such as '!'. |
365 |
- """ |
366 |
- |
367 |
- alias_count = len ( self.dep_alias ) |
368 |
- |
369 |
- retlist = [] |
370 |
- |
371 |
- if alias_count: |
372 |
- if resolving_to is None: |
373 |
- if hasattr ( self, 'resolving_package'): |
374 |
- resolving_package = self.resolving_package |
375 |
- else: |
376 |
- resolving_package = '!' |
377 |
- else: |
378 |
- resolving_package = resolving_to |
379 |
- |
380 |
- # todo hardcoded rule format here |
381 |
- if alias_count > 1: |
382 |
- |
383 |
- retlist = [ resolving_package + ' {\n' ] + \ |
384 |
- [ "\t%s\n" % alias for alias in self.dep_alias ] + \ |
385 |
- [ '}\n' ] |
386 |
- else: |
387 |
- retlist = [ |
388 |
- "%s :: %s\n" % ( resolving_package, self.dep_alias [0] ) |
389 |
- ] |
390 |
- |
391 |
- # -- if |
392 |
- |
393 |
- return retlist |
394 |
- # --- end of export_rule (...) --- |
395 |
+class SimpleIgnoreDependencyRule ( SimpleRule ): |
396 |
|
397 |
+ def __init__ ( self, dep_str=None, priority=50, resolving_package=None ): |
398 |
+ super ( SimpleIgnoreDependencyRule, self ) . __init__ ( |
399 |
+ dep_str=dep_str, |
400 |
+ priority=priority, |
401 |
+ resolving_package=None, |
402 |
+ logger_name = 'IGNORE_DEPS', |
403 |
+ ) |
404 |
|
405 |
-class SimpleDependencyRule ( SimpleIgnoreDependencyRule ): |
406 |
+class SimpleDependencyRule ( SimpleRule ): |
407 |
|
408 |
def __init__ ( self, resolving_package, dep_str=None, priority=70 ): |
409 |
"""Initializes a SimpleDependencyRule. This is |
410 |
@@ -132,21 +33,32 @@ class SimpleDependencyRule ( SimpleIgnoreDependencyRule ): |
411 |
* priority -- |
412 |
""" |
413 |
super ( SimpleDependencyRule, self ) . __init__ ( |
414 |
- dep_str=dep_str, priority=priority |
415 |
+ dep_str=dep_str, |
416 |
+ priority=priority, |
417 |
+ resolving_package=resolving_package, |
418 |
+ logger_name=resolving_package |
419 |
) |
420 |
|
421 |
- self.resolving_package = resolving_package |
422 |
+ # --- end of __init__ (...) --- |
423 |
|
424 |
- self.logger = TMP_LOGGER.getChild ( resolving_package ) |
425 |
+class SimpleFuzzyIgnoreDependencyRule ( FuzzySimpleRule ): |
426 |
|
427 |
- # --- end of __init__ (...) --- |
428 |
+ def __init__ ( self, dep_str=None, priority=51, resolving_package=None ): |
429 |
+ super ( SimpleFuzzyIgnoreDependencyRule, self ) . __init__ ( |
430 |
+ dep_str=dep_str, |
431 |
+ priority=priority, |
432 |
+ resolving_package=None, |
433 |
+ logger_name = 'FUZZY.IGNORE_DEPS', |
434 |
+ ) |
435 |
|
436 |
- def get_dep ( self ): |
437 |
- """Returns the textual portage package representation of this rule, |
438 |
- e.g. 'dev-lang/R'. |
439 |
- """ |
440 |
- return self.resolving_package |
441 |
- # --- end of get_dep (...) --- |
442 |
+class SimpleFuzzyDependencyRule ( FuzzySimpleRule ): |
443 |
+ def __init__ ( self, resolving_package, dep_str=None, priority=71 ): |
444 |
+ super ( SimpleFuzzyDependencyRule, self ) . __init__ ( |
445 |
+ dep_str=dep_str, |
446 |
+ priority=priority, |
447 |
+ resolving_package=resolving_package, |
448 |
+ logger_name = 'FUZZY.' + resolving_package, |
449 |
+ ) |
450 |
|
451 |
|
452 |
class SimpleDependencyRulePool ( deprule.DependencyRulePool ): |
453 |
@@ -175,7 +87,7 @@ class SimpleDependencyRulePool ( deprule.DependencyRulePool ): |
454 |
arguments: |
455 |
* rule -- |
456 |
""" |
457 |
- if isinstance ( rule, SimpleIgnoreDependencyRule ): |
458 |
+ if isinstance ( rule, SimpleRule ): |
459 |
self.rules.append ( rule ) |
460 |
else: |
461 |
raise Exception ( "bad usage (simple dependency rule expected)." ) |
462 |
@@ -220,8 +132,13 @@ class SimpleDependencyRuleReader ( object ): |
463 |
multiline_start = '{' |
464 |
multiline_stop = '}' |
465 |
comment_chars = "#;" |
466 |
+ |
467 |
# todo: const/config? |
468 |
- package_ignore = [ '!' ] |
469 |
+ package_ignore = '!' |
470 |
+ fuzzy = '~' |
471 |
+ fuzzy_ignore = '%' |
472 |
+ |
473 |
+ BREAK_PARSING = frozenset (( '#! NOPARSE', '#! BREAK' )) |
474 |
|
475 |
|
476 |
def __init__ ( self ): |
477 |
@@ -229,6 +146,12 @@ class SimpleDependencyRuleReader ( object ): |
478 |
pass |
479 |
# --- end of __init__ (...) --- |
480 |
|
481 |
+ |
482 |
+ def _make_rule ( self, rule_str ): |
483 |
+ CLS = self.__class__ |
484 |
+ |
485 |
+ |
486 |
+ |
487 |
def read_file ( self, filepath ): |
488 |
"""Reads a file that contains simple dependency rules |
489 |
(SimpleIgnoreDependencyRules/SimpleDependencyRules). |
490 |
@@ -244,6 +167,8 @@ class SimpleDependencyRuleReader ( object ): |
491 |
logging.debug ( "Reading simple dependency rule file %s." % filepath ) |
492 |
fh = open ( filepath, 'r' ) |
493 |
|
494 |
+ CLS = self.__class__ |
495 |
+ |
496 |
# the list of read rules |
497 |
rules = list () |
498 |
|
499 |
@@ -258,47 +183,95 @@ class SimpleDependencyRuleReader ( object ): |
500 |
# empty |
501 |
pass |
502 |
|
503 |
+ elif line in CLS.BREAK_PARSING: |
504 |
+ # stop reading here |
505 |
+ break |
506 |
+ |
507 |
elif not next_rule is None: |
508 |
# in a multiline rule |
509 |
|
510 |
- if line [0] == SimpleDependencyRuleReader.multiline_stop: |
511 |
+ if line [0] == CLS.multiline_stop: |
512 |
# end of a multiline rule, |
513 |
# add rule to rules and set next_rule to None |
514 |
+ next_rule.done_reading() |
515 |
rules.append ( next_rule ) |
516 |
next_rule = None |
517 |
else: |
518 |
# new resolved str |
519 |
next_rule.add_resolved ( line ) |
520 |
|
521 |
- elif line [0] in SimpleDependencyRuleReader.comment_chars: |
522 |
+ elif line [0] in CLS.comment_chars: |
523 |
# comment |
524 |
# it is intented that multi line rules cannot contain comments |
525 |
pass |
526 |
|
527 |
- elif line [-1] == SimpleDependencyRuleReader.multiline_start: |
528 |
+ elif line [-1] == CLS.multiline_start: |
529 |
# start of a multiline rule |
530 |
portpkg = line [:-1].rstrip() |
531 |
- if portpkg in SimpleDependencyRuleReader.package_ignore: |
532 |
+ |
533 |
+ if portpkg == CLS.fuzzy_ignore: |
534 |
+ next_rule = SimpleFuzzyIgnoreDependencyRule ( None ) |
535 |
+ elif portpkg == CLS.fuzzy: |
536 |
+ next_rule = SimpleFuzzyDependencyRule ( portpkg[1:], None ) |
537 |
+ elif portpkg == CLS.package_ignore: |
538 |
next_rule = SimpleIgnoreDependencyRule ( None, 60 ) |
539 |
else: |
540 |
next_rule = SimpleDependencyRule ( portpkg, None, 70 ) |
541 |
|
542 |
else: |
543 |
- # single line rule? |
544 |
- rule_str = \ |
545 |
- SimpleDependencyRuleReader.one_line_separator.split (line, 1) |
546 |
+ # single line rule, either selfdep, |
547 |
+ # e.g. '~zoo' -> fuzzy sci-R/zoo :: zoo |
548 |
+ # or normal rule 'dev-lang/R :: R' |
549 |
+ # selfdeps are always single line statements (!) |
550 |
+ rule_str = CLS.one_line_separator.split (line, 1) |
551 |
+ |
552 |
+ new_rule = None |
553 |
+ rule_class = None |
554 |
+ resolving = None |
555 |
+ |
556 |
+ first_char = rule_str [0][0] if len ( rule_str [0] ) else '' |
557 |
+ |
558 |
+ if first_char == CLS.fuzzy: |
559 |
+ rule_class = SimpleFuzzyDependencyRule |
560 |
+ resolving = rule_str [0] [1:] |
561 |
+ |
562 |
+ elif rule_str [0] == CLS.fuzzy_ignore: |
563 |
+ rule_class = SimpleFuzzyIgnoreDependencyRule |
564 |
+ resolving = None |
565 |
+ |
566 |
+ elif rule_str [0] == CLS.package_ignore: |
567 |
+ rule_class = SimpleIgnoreDependencyRule |
568 |
+ |
569 |
+ else: |
570 |
+ rule_class = SimpleDependencyRule |
571 |
+ resolving = rule_str [0] |
572 |
|
573 |
if len ( rule_str ) == 2: |
574 |
- # is a single line rule |
575 |
- |
576 |
- if rule_str [0] in SimpleDependencyRuleReader.package_ignore: |
577 |
- rules.append ( |
578 |
- SimpleIgnoreDependencyRule ( rule_str [1], 40 ) |
579 |
- ) |
580 |
- else: |
581 |
- rules.append ( |
582 |
- SimpleDependencyRule ( rule_str [0], rule_str [1], 50 ) |
583 |
- ) |
584 |
+ # normal rule |
585 |
+ new_rule = rule_class ( |
586 |
+ resolving_package=resolving, |
587 |
+ dep_str=rule_str [1] |
588 |
+ ) |
589 |
+ |
590 |
+ elif resolving is not None: |
591 |
+ # selfdep |
592 |
+ dep_str = resolving |
593 |
+ resolving = '/'.join ( ( |
594 |
+ config.get_or_fail ( 'OVERLAY.category' ), |
595 |
+ resolving |
596 |
+ ) ) |
597 |
+ new_rule = rule_class ( |
598 |
+ resolving_package=resolving, |
599 |
+ dep_str=dep_str |
600 |
+ ) |
601 |
+ |
602 |
+ # else: error |
603 |
+ |
604 |
+ |
605 |
+ if new_rule: |
606 |
+ new_rule.done_reading() |
607 |
+ rules.append ( new_rule ) |
608 |
+ |
609 |
else: |
610 |
logging.error ( |
611 |
"In %s, line %i : cannot use this line." % |
612 |
@@ -308,6 +281,9 @@ class SimpleDependencyRuleReader ( object ): |
613 |
|
614 |
if fh: fh.close () |
615 |
|
616 |
+ if next_rule is not None: |
617 |
+ logging.warning ( "Multi line rule does not end at EOF - ignored" ) |
618 |
+ |
619 |
logging.info ( |
620 |
"%s: read %i dependency rules (in %i lines)" % |
621 |
( filepath, len ( rules ), lineno ) |