def __new__(cls,targets,reqs,order_only=None,func=None,PHONY=False,shared=False): """selects and creates the appropriate rule class to use. All rule instances can also be used as decorators around build recipe functions (in this case leave func=None). targets - single target or sequence of targets reqs - single prerequisite or sequence of prerequisites order_only - single dependency or sequence of order only prerequisites func - the build function that should take one or no arguments. Will be passed this class instance when run in order to have access to its attributes. PHONY - a phony rule always runs irrespective of file modification times shared - shared rules run their build function a single time for all of their targets. targets and reqs may contain glob patterns (see fnmatch and glob modules). They may also contain the '%' wildcard for defining pattern rules (like make). """ targets = checkseq(targets) reqs = checkseq(reqs) order_only = checkseq(order_only) if shared: if not any(fpmatch.has_magic(target) for target in targets): targets = [fpmatch.strip_specials(target) for target in targets] if not any(fpmatch.has_magic(req) for req in itertools.chain(reqs,order_only)): reqs = [fpmatch.strip_specials(req) for req in reqs] newrule = ExplicitRule(targets,reqs,order_only,func,PHONY) else: newrule = ExplicitTargetRule(targets,reqs,order_only,func,PHONY) elif any(fpmatch.has_pattern(target) for target in targets): #in fact all targets should have a pattern wildcard but error checking will occur in class. newrule = PatternSharedRule(targets,reqs,order_only,func,PHONY) else: #wildcard targets newrule = WildSharedRule(targets,reqs,order_only,func,PHONY) else: if not any(fpmatch.has_magic(target) for target in targets): targets = [fpmatch.strip_specials(target) for target in targets] if not any(fpmatch.has_magic(req) for req in itertools.chain(reqs,order_only)): reqs = [fpmatch.strip_specials(req) for req in reqs] if len(targets)<=1: newrule = ExplicitRule(targets,reqs,order_only,func,PHONY) else: newrule = ManyRules(ExplicitRule(target,reqs,order_only,func,PHONY) for target in targets) #or maybe use WildRule?? else: if len(targets)<=1: newrule = ExplicitTargetRule(targets,reqs,order_only,func,PHONY) else: newrule = ManyRules(ExplicitTargetRule(target,reqs,order_only,func,PHONY) for target in targets) #or maybe use WildRule?? elif any(fpmatch.has_pattern(target) for target in targets): #in fact all targets should have a pattern wildcard but error checking will occur in class. newrule = PatternRule(targets,reqs,order_only,func,PHONY) else: #wildcard targets newrule = WildRule(targets,reqs,order_only,func,PHONY) return newrule
def test_pattern_with_subdirectories(self): def test_general_pattern_match(self): def teardown(self): pass #is this a bug? assert fpmatch.strip_specials('test[]]time') != 'test]time' #not sure this is a bug though #question fpmatch.strip_specials('test[abcd].txt') == 'test.txt' #this is what we want isn't it? #but fpmatch.strip_specials('test[*].txt') == 'test.txt' # is this really what we want?
def __init__(self,targets,reqs,order_only=None,func=None,PHONY=False): """targets - list of targets reqs - seq of prerequisites order_only - seq of order only prerequisites func - a function that should take one or no arguments. Will be passed this class instance when run in order to have access to its attributes. """ self.targets = targets = checkseq(targets) self.PHONY = PHONY self.allreqs = reqs = checkseq(reqs) self.order_only = order_only = checkseq(order_only) self.explicit_rules = [] #each meta_rule remembers its explicit rules. self._func = func #Add self to registry of rules wild_targets = fpmatch.only_wild_paths(targets) self.re_targets = [fpmatch.precompile(pattern) for pattern in wild_targets] for regex in self.re_targets: self.rules[regex] = self #calculate pattern lengths rankings = [len(fpmatch.strip_specials(pattern)) for pattern in wild_targets] for regex,rank in zip(self.re_targets,rankings): self._pattern_rankings[regex] = rank
def expand_wildcard(self,fpath): """Uses the glob module to search the file system and an altered glob module - fpmatch to search the meta rules. """ matches = glob.glob(fpath) if fpmatch.has_magic(fpath): matches += fpmatch.filter(self.rules.iterkeys(),fpath) else: matches += [fpmatch.strip_specials(fpath)] #can still have single escaped chars in sets when magic==False if len(matches) == 0: raise AssertionError("No matching file or rule found for %r" %fpath) return dedup(matches)