# HG changeset patch # User Jeff Hammel # Date 1322173556 28800 # Node ID 4566b3ac9838d99d72f2634e2bd276ffde390455 # Parent 0b51868bdfb9419fc59a75d09f38d1f807bb9e07 this may almost work diff -r 0b51868bdfb9 -r 4566b3ac9838 licenser/licenses.py --- a/licenser/licenses.py Thu Nov 24 13:03:15 2011 -0800 +++ b/licenser/licenses.py Thu Nov 24 14:25:56 2011 -0800 @@ -42,28 +42,92 @@ # types of comments -def asterisk_omments(): - pass +class CommentedFile(object): + + extensions = set() + + @classmethod + def match(cls, filename): + basename, extension = os.path.splitext(os.path.basename(filename)) + if extension in extensions: + return cls(filename) + + def __init__(self, filename): + self.filename = filename + + def isempty(self): + return bool(file(self.filename).read().strip) + + def lines(self): + if hasattr(self, '_lines'): + return self._lines + self._lines = file(self.filename).readlines() + return self._lines + +class AsteriskCommentsFile(CommentedFile): + + extensions = set(['c']) + + def __call__(self, license): + + # open the file for writing + raise NotImplementedError + +class HashCommentsFile(object): + + extensions = set(['py', 'sh']) -def hash_comments(): - pass + def __call__(self, license): + """interpolate the file""" + + if self.isempty(): + return # you're done + lines = self.lines() + + # open the file for writing + f = file(self.filename, 'w') + + # print shebang if it exists + if lines[0].startswith('#!'): + shebang = lines.pop(0).strip() + print >> f, shebang + print >> f + + # print the license + f.write(license) -suffixes = {'py': hash_comments, - 'sh': hash_comments, - 'c': asterisk_comments} + # print the rest of the file + for line in lines: + f.write(line) + f.close() + + + def isempty(self, path): + """ + determines if a file is empty; that is, contains only comments + """ + for line in self.lines() + line = line.strip() + if line and line[0] != '#': + return False + return True + + +filetypes = [HashCommentsFile, AsteriskCommentsFile] class License(object): """Abstract base class for a license""" variables = [] # required variables - def __init__(self): + def __init__(self, filetypes=self.filetypes[:]): if self.template: if not os.path.isabs(self.template): self.template = os.path.join(os.path.dirname(__file__), 'licenses', self.template) assert os.path.exists(self.template) + self.filetypes = filetypes def license(self): return file(self.template).read() @@ -95,90 +159,80 @@ self.pre(kw) return kw - def pre(self, variables): - """do anything that needs to be done with the variables before interpolation""" - - def interpolate_file(self, _file, variables): - - # get the file lines - f = file(_file) - lines = [ i.rstrip() for i in f.readlines() ] - f.close() - - # open the file for writing - f = file(_file, 'w') + def pre(self, variables): + """do anything that needs to be done with the variables before interpolation""" - # print shebang if it exists - if lines[0].startswith('#!'): - shebang = lines.pop(0) - print >> f, shebang - print >> f + def filetype(self, _file): + """determine the filetype for a given file""" + for filetype in self.filetypes: + match = filetype.match(_file) + if match: + return match - # print the license - g = self.license() - for line in g.splitlines(): - line = line.rstrip() - _template = Template(line) - print >> f, '# %s' % _template.substitute(**variables) - g.close() + def interpolate_file(self, _file, variables): + + # if the file is licensed, no need to proceed + if self.has_license(filename): + return # you're done - # print the rest of the file - for line in lines: - print >> f, line.rstrip() - f.close() + # get the filetype + filetype = self.filetype(_file) + if not filetype: + return # you're done - def interpolate(self, directory, variables): - for _file in self.files(directory): - self.interpolate_file(_file, variables) + # get the license + # XXX should be cached + license = self.license() + license = Template(license).substitute(**variables) - def isempty(self, path): - """ - determines if a python file is empty; that is, contains only comments - """ - for line in file(path, 'r').readlines(): - line = line.strip() - if line and line[0] != '#': - return False - return True + # add the license to the file + filetype(license) + + def interpolate(self, directory, variables): + for _file in self.files(directory): + self.interpolate_file(_file, variables) - def files(self, directory): - files = set() - for dirpath, _, filenames in os.walk(directory): - for f in filenames: - if f.endswith('.py'): # could use os.path.splitext() + def files(self, directory): + files = set() + for dirpath, _, filenames in os.walk(directory): + for f in filenames: path = os.path.join(dirpath, f) - if not self.isempty(path): - files.add(path) - return files + return files class MPL(License): - """Mozilla Public License""" - template = 'MPL' # could be implicit here - variables = [ 'author', 'email' ] - url = 'http://www.mozilla.org/MPL/boilerplate-1.1/mpl-tri-license-txt' + """Mozilla Public License""" + template = 'MPL' # could be implicit here + variables = [ 'author', 'email' ] + url = 'http://www.mozilla.org/MPL/boilerplate-1.1/mpl-tri-license-txt' + + def license(self): - def license(self): - # get the raw license - raw = urllib2.urlopen(self.url).read() + if hasattr(self, '_license'): + # return the cached copy + return self._license + + # get the raw license + raw = urllib2.urlopen(self.url).read() - # now make it something not crazy - lines = raw.splitlines() - contributor_index = None - for index, line in enumerate(lines): - if line.startswith('The Original Code is'): - lines[index] = 'The Original Code is mozilla.org code.' - if line.startswith('_'): - lines[index] = 'the Mozilla Foundation.' - if '2___' in line: - lines[index] = line.replace('2___', '${year}') - if line.startswith('Contributor'): - contributor_index = index + # now make it something not crazy + lines = raw.splitlines() + contributor_index = None + for index, line in enumerate(lines): + if line.startswith('The Original Code is'): + lines[index] = 'The Original Code is mozilla.org code.' + if line.startswith('_'): + lines[index] = 'the Mozilla Foundation.' + if '2___' in line: + lines[index] = line.replace('2___', '${year}') + if line.startswith('Contributor'): + contributor_index = index - assert contributor_index - lines.insert(contributor_index+1, ' ${author} <${email}>') - return '\n'.join(lines) + assert contributor_index + lines.insert(contributor_index+1, ' ${author} <${email}>') + self._license = '\n'.join(lines) + return self._license - def pre(self, variables): - variables['year'] = datetime.now().year + def pre(self, variables): + variables['year'] = datetime.now().year