mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			161 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			161 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
#!/usr/bin/env python
 | 
						|
"""Script to locate email addresses in the CVS logs."""
 | 
						|
__version__ = '$Revision$'
 | 
						|
 | 
						|
import os
 | 
						|
import re
 | 
						|
import sys
 | 
						|
import UserDict
 | 
						|
 | 
						|
import cvsinfo
 | 
						|
 | 
						|
 | 
						|
class Acknowledgements(UserDict.UserDict):
 | 
						|
    def add(self, email, name, path):
 | 
						|
        d = self.data
 | 
						|
        d.setdefault(email, {})[path] = name
 | 
						|
 | 
						|
 | 
						|
def open_cvs_log(info, paths=None):
 | 
						|
    cvsroot = info.get_cvsroot()
 | 
						|
    cmd = "cvs -q -d%s log " % cvsroot
 | 
						|
    if paths:
 | 
						|
        cmd += " ".join(paths)
 | 
						|
    return os.popen(cmd, "r")
 | 
						|
 | 
						|
 | 
						|
email_rx = re.compile("<([a-z][-a-z0-9._]*@[-a-z0-9.]+)>", re.IGNORECASE)
 | 
						|
 | 
						|
def find_acks(f, acks):
 | 
						|
    prev = ''
 | 
						|
    filename = None
 | 
						|
    MAGIC_WORDS = ('van', 'von')
 | 
						|
    while 1:
 | 
						|
        line = f.readline()
 | 
						|
        if not line:
 | 
						|
            break
 | 
						|
        if line.startswith("Working file: "):
 | 
						|
            filename = line.split(None, 2)[2].strip()
 | 
						|
            prev = line
 | 
						|
            continue
 | 
						|
        m = email_rx.search(line)
 | 
						|
        if m:
 | 
						|
            words = prev.split() + line[:m.start()].split()
 | 
						|
            L = []
 | 
						|
            while words \
 | 
						|
                  and (words[-1][0].isupper() or words[-1] in MAGIC_WORDS):
 | 
						|
                L.insert(0, words.pop())
 | 
						|
            name = " ".join(L)
 | 
						|
            email = m.group(1).lower()
 | 
						|
            acks.add(email, name, filename)
 | 
						|
        prev = line
 | 
						|
 | 
						|
 | 
						|
def load_cvs_log_acks(acks, args):
 | 
						|
    repolist = cvsinfo.get_repository_list(args or [""])
 | 
						|
    for info, paths in repolist:
 | 
						|
        print >>sys.stderr, "Repository:", info.get_cvsroot()
 | 
						|
        f = open_cvs_log(info, paths)
 | 
						|
        find_acks(f, acks)
 | 
						|
        f.close()
 | 
						|
 | 
						|
 | 
						|
def load_tex_source_acks(acks, args):
 | 
						|
    for path in args:
 | 
						|
        path = path or os.curdir
 | 
						|
        if os.path.isfile(path):
 | 
						|
            read_acks_from_tex_file(acks, path)
 | 
						|
        else:
 | 
						|
            read_acks_from_tex_dir(acks, path)
 | 
						|
 | 
						|
 | 
						|
def read_acks_from_tex_file(acks, path):
 | 
						|
    f = open(path)
 | 
						|
    while 1:
 | 
						|
        line = f.readline()
 | 
						|
        if not line:
 | 
						|
            break
 | 
						|
        if line.startswith(r"\sectionauthor{"):
 | 
						|
            line = line[len(r"\sectionauthor"):]
 | 
						|
            name, line = extract_tex_group(line)
 | 
						|
            email, line = extract_tex_group(line)
 | 
						|
            acks.add(email, name, path)
 | 
						|
 | 
						|
 | 
						|
def read_acks_from_tex_dir(acks, path):
 | 
						|
    stack = [path]
 | 
						|
    while stack:
 | 
						|
        p = stack.pop()
 | 
						|
        for n in os.listdir(p):
 | 
						|
            n = os.path.join(p, n)
 | 
						|
            if os.path.isdir(n):
 | 
						|
                stack.insert(0, n)
 | 
						|
            elif os.path.normpath(n).endswith(".tex"):
 | 
						|
                read_acks_from_tex_file(acks, n)
 | 
						|
 | 
						|
 | 
						|
def extract_tex_group(s):
 | 
						|
    c = 0
 | 
						|
    for i in range(len(s)):
 | 
						|
        if s[i] == '{':
 | 
						|
            c += 1
 | 
						|
        elif s[i] == '}':
 | 
						|
            c -= 1
 | 
						|
            if c == 0:
 | 
						|
                return s[1:i], s[i+1:]
 | 
						|
 | 
						|
 | 
						|
def print_acks(acks):
 | 
						|
    first = 1
 | 
						|
    for email, D in acks.items():
 | 
						|
        if first:
 | 
						|
            first = 0
 | 
						|
        else:
 | 
						|
            print
 | 
						|
        L = D.items()
 | 
						|
        L.sort()
 | 
						|
        prefname = L[0][1]
 | 
						|
        for file, name in L[1:]:
 | 
						|
            if name != prefname:
 | 
						|
                prefname = ""
 | 
						|
                break
 | 
						|
        if prefname:
 | 
						|
            print prefname, "<%s>:" % email
 | 
						|
        else:
 | 
						|
            print email + ":"
 | 
						|
        for file, name in L:
 | 
						|
            if name == prefname:
 | 
						|
                print "    " + file
 | 
						|
            else:
 | 
						|
                print "    %s (as %s)" % (file, name)
 | 
						|
 | 
						|
 | 
						|
def print_ack_names(acks):
 | 
						|
    names = []
 | 
						|
    for email, D in acks.items():
 | 
						|
        L = D.items()
 | 
						|
        L.sort()
 | 
						|
        prefname = L[0][1]
 | 
						|
        for file, name in L[1:]:
 | 
						|
            prefname = prefname or name
 | 
						|
        names.append(prefname or email)
 | 
						|
    def f(s1, s2):
 | 
						|
        s1 = s1.lower()
 | 
						|
        s2 = s2.lower()
 | 
						|
        return cmp((s1.split()[-1], s1),
 | 
						|
                   (s2.split()[-1], s2))
 | 
						|
    names.sort(f)
 | 
						|
    for name in names:
 | 
						|
        print name
 | 
						|
 | 
						|
 | 
						|
def main():
 | 
						|
    args = sys.argv[1:]
 | 
						|
    acks = Acknowledgements()
 | 
						|
    load_cvs_log_acks(acks, args)
 | 
						|
    load_tex_source_acks(acks, args)
 | 
						|
    print_ack_names(acks)
 | 
						|
 | 
						|
 | 
						|
if __name__ == "__main__":
 | 
						|
    main()
 |