#!/usr/bin/env python# encoding: utf-8# Copyright 2009 Baptiste Lepilleur and The JsonCpp Authors# Distributed under MIT license, or public domain if desired and# recognized in your jurisdiction.# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSEfrom __future__ import print_functionfrom dircache import listdirimport reimport fnmatchimport os.path# These fnmatch expressions are used by default to prune the directory tree# while doing the recursive traversal in the glob_impl method of glob function.prune_dirs = '.git .bzr .hg .svn _MTN _darcs CVS SCCS '# These fnmatch expressions are used by default to exclude files and dirs# while doing the recursive traversal in the glob_impl method of glob function.##exclude_pats = prune_pats + '*~ #*# .#* %*% ._* .gitignore .cvsignore vssver.scc .DS_Store'.split()# These ant_glob expressions are used by default to exclude files and dirs and also prune the directory tree# while doing the recursive traversal in the glob_impl method of glob function.default_excludes = '''**/*~**/#*#**/.#***/%*%**/._***/CVS**/CVS/****/.cvsignore**/SCCS**/SCCS/****/vssver.scc**/.svn**/.svn/****/.git**/.git/****/.gitignore**/.bzr**/.bzr/****/.hg**/.hg/****/_MTN**/_MTN/****/_darcs**/_darcs/****/.DS_Store '''DIR = 1FILE = 2DIR_LINK = 4FILE_LINK = 8LINKS = DIR_LINK | FILE_LINKALL_NO_LINK = DIR | FILEALL = DIR | FILE | LINKS_ANT_RE = re.compile(r'(/\*\*/)|(\*\*/)|(/\*\*)|(\*)|(/)|([^\*/]*)')def ant_pattern_to_re(ant_pattern):"""Generates a regular expression from the ant pattern.Matching convention:**/a: match 'a', 'dir/a', 'dir1/dir2/a'a/**/b: match 'a/b', 'a/c/b', 'a/d/c/b'*.py: match 'script.py' but not 'a/script.py'"""rex = ['^']next_pos = 0sep_rex = r'(?:/|%s)' % re.escape(os.path.sep)## print 'Converting', ant_patternfor match in _ANT_RE.finditer(ant_pattern):## print 'Matched', match.group()## print match.start(0), next_posif match.start(0) != next_pos:raise ValueError("Invalid ant pattern")if match.group(1): # /**/rex.append(sep_rex + '(?:.*%s)?' % sep_rex)elif match.group(2): # **/rex.append('(?:.*%s)?' % sep_rex)elif match.group(3): # /**rex.append(sep_rex + '.*')elif match.group(4): # *rex.append('[^/%s]*' % re.escape(os.path.sep))elif match.group(5): # /rex.append(sep_rex)else: # somepathrex.append(re.escape(match.group(6)))next_pos = match.end()rex.append('$')return re.compile(''.join(rex))def _as_list(l):if isinstance(l, basestring):return l.split()return ldef glob(dir_path,includes = '**/*',excludes = default_excludes,entry_type = FILE,prune_dirs = prune_dirs,max_depth = 25):include_filter = [ant_pattern_to_re(p) for p in _as_list(includes)]exclude_filter = [ant_pattern_to_re(p) for p in _as_list(excludes)]prune_dirs = [p.replace('/',os.path.sep) for p in _as_list(prune_dirs)]dir_path = dir_path.replace('/',os.path.sep)entry_type_filter = entry_typedef is_pruned_dir(dir_name):for pattern in prune_dirs:if fnmatch.fnmatch(dir_name, pattern):return Truereturn Falsedef apply_filter(full_path, filter_rexs):"""Return True if at least one of the filter regular expression match full_path."""for rex in filter_rexs:if rex.match(full_path):return Truereturn Falsedef glob_impl(root_dir_path):child_dirs = [root_dir_path]while child_dirs:dir_path = child_dirs.pop()for entry in listdir(dir_path):full_path = os.path.join(dir_path, entry)## print 'Testing:', full_path,is_dir = os.path.isdir(full_path)if is_dir and not is_pruned_dir(entry): # explore child directory ?## print '===> marked for recursion',child_dirs.append(full_path)included = apply_filter(full_path, include_filter)rejected = apply_filter(full_path, exclude_filter)if not included or rejected: # do not include entry ?## print '=> not included or rejected'continuelink = os.path.islink(full_path)is_file = os.path.isfile(full_path)if not is_file and not is_dir:## print '=> unknown entry type'continueif link:entry_type = is_file and FILE_LINK or DIR_LINKelse:entry_type = is_file and FILE or DIR## print '=> type: %d' % entry_type,if (entry_type & entry_type_filter) != 0:## print ' => KEEP'yield os.path.join(dir_path, entry)## else:## print ' => TYPE REJECTED'return list(glob_impl(dir_path))if __name__ == "__main__":import unittestclass AntPatternToRETest(unittest.TestCase):## def test_conversion(self):## self.assertEqual('^somepath$', ant_pattern_to_re('somepath').pattern)def test_matching(self):test_cases = [ ('path',['path'],['somepath', 'pathsuffix', '/path', '/path']),('*.py',['source.py', 'source.ext.py', '.py'],['path/source.py', '/.py', 'dir.py/z', 'z.pyc', 'z.c']),('**/path',['path', '/path', '/a/path', 'c:/a/path', '/a/b/path', '//a/path', '/a/path/b/path'],['path/', 'a/path/b', 'dir.py/z', 'somepath', 'pathsuffix', 'a/somepath']),('path/**',['path/a', 'path/path/a', 'path//'],['path', 'somepath/a', 'a/path', 'a/path/a', 'pathsuffix/a']),('/**/path',['/path', '/a/path', '/a/b/path/path', '/path/path'],['path', 'path/', 'a/path', '/pathsuffix', '/somepath']),('a/b',['a/b'],['somea/b', 'a/bsuffix', 'a/b/c']),('**/*.py',['script.py', 'src/script.py', 'a/b/script.py', '/a/b/script.py'],['script.pyc', 'script.pyo', 'a.py/b']),('src/**/*.py',['src/a.py', 'src/dir/a.py'],['a/src/a.py', '/src/a.py']),]for ant_pattern, accepted_matches, rejected_matches in list(test_cases):def local_path(paths):return [ p.replace('/',os.path.sep) for p in paths ]test_cases.append((ant_pattern, local_path(accepted_matches), local_path(rejected_matches)))for ant_pattern, accepted_matches, rejected_matches in test_cases:rex = ant_pattern_to_re(ant_pattern)print('ant_pattern:', ant_pattern, ' => ', rex.pattern)for accepted_match in accepted_matches:print('Accepted?:', accepted_match)self.assertTrue(rex.match(accepted_match) is not None)for rejected_match in rejected_matches:print('Rejected?:', rejected_match)self.assertTrue(rex.match(rejected_match) is None)unittest.main()
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。