changeset 17:4566b3ac9838

this may almost work
author Jeff Hammel <jhammel@mozilla.com>
date Thu, 24 Nov 2011 14:25:56 -0800
parents 0b51868bdfb9
children c04a53145f19
files licenser/licenses.py
diffstat 1 files changed, 134 insertions(+), 80 deletions(-) [+]
line wrap: on
line diff
--- 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