[Checkins] SVN: zope.repositorypolicy/trunk/ Import tools that can be used to:

Christian Theune ct at gocept.com
Fri Mar 5 10:08:07 EST 2010


Log message for revision 109677:
  Import tools that can be used to:
  
  - continuously monitor the repository compliance
  - check for issues in a working directory
  - some helpers for fixing copyright headers
  

Changed:
  A   zope.repositorypolicy/trunk/
  A   zope.repositorypolicy/trunk/RULES.txt
  A   zope.repositorypolicy/trunk/bootstrap.py
  A   zope.repositorypolicy/trunk/buildout.cfg
  A   zope.repositorypolicy/trunk/setup.py
  A   zope.repositorypolicy/trunk/src/
  A   zope.repositorypolicy/trunk/src/zope/
  A   zope.repositorypolicy/trunk/src/zope/__init__.py
  A   zope.repositorypolicy/trunk/src/zope/repositorypolicy/
  A   zope.repositorypolicy/trunk/src/zope/repositorypolicy/__init__.py
  A   zope.repositorypolicy/trunk/src/zope/repositorypolicy/copyright.py
  A   zope.repositorypolicy/trunk/src/zope/repositorypolicy/data/
  A   zope.repositorypolicy/trunk/src/zope/repositorypolicy/data/ZPL-2.1.txt
  A   zope.repositorypolicy/trunk/src/zope/repositorypolicy/project.py
  A   zope.repositorypolicy/trunk/src/zope/repositorypolicy/repository.py

-=-
Added: zope.repositorypolicy/trunk/RULES.txt
===================================================================
--- zope.repositorypolicy/trunk/RULES.txt	                        (rev 0)
+++ zope.repositorypolicy/trunk/RULES.txt	2010-03-05 15:08:06 UTC (rev 109677)
@@ -0,0 +1,15 @@
+
+- the rules are enforced on all top level subversion modules on the branches
+  trunk, develop
+
+- the rules are *not* enforced in the modules
+  Sandbox, ...
+
+
+- all copyright headers (c-style, python style) must be zope foundation
+
+- every package must have a license.txt which is ZPL 2.1
+- every package must have a copyright.txt according to ZPL 2.1 which points to
+  the Zope Foundation
+
+- exceptions to the rules are codified in each package in a special file


Property changes on: zope.repositorypolicy/trunk/RULES.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: zope.repositorypolicy/trunk/bootstrap.py
===================================================================
--- zope.repositorypolicy/trunk/bootstrap.py	                        (rev 0)
+++ zope.repositorypolicy/trunk/bootstrap.py	2010-03-05 15:08:06 UTC (rev 109677)
@@ -0,0 +1,77 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id: bootstrap.py 90478 2008-08-27 22:44:46Z georgyberdyshev $
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+is_jython = sys.platform.startswith('java')
+
+try:
+    import pkg_resources
+except ImportError:
+    ez = {}
+    exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+                         ).read() in ez
+    ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+    import pkg_resources
+
+if sys.platform == 'win32':
+    def quote(c):
+        if ' ' in c:
+            return '"%s"' % c # work around spawn lamosity on windows
+        else:
+            return c
+else:
+    def quote (c):
+        return c
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+ws  = pkg_resources.working_set
+
+if is_jython:
+    import subprocess
+    
+    assert subprocess.Popen([sys.executable] + ['-c', quote(cmd), '-mqNxd', 
+           quote(tmpeggs), 'zc.buildout'], 
+           env=dict(os.environ,
+               PYTHONPATH=
+               ws.find(pkg_resources.Requirement.parse('setuptools')).location
+               ),
+           ).wait() == 0
+
+else:
+    assert os.spawnle(
+        os.P_WAIT, sys.executable, quote (sys.executable),
+        '-c', quote (cmd), '-mqNxd', quote (tmpeggs), 'zc.buildout',
+        dict(os.environ,
+            PYTHONPATH=
+            ws.find(pkg_resources.Requirement.parse('setuptools')).location
+            ),
+        ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)


Property changes on: zope.repositorypolicy/trunk/bootstrap.py
___________________________________________________________________
Added: svn:eol-style
   + native

Added: zope.repositorypolicy/trunk/buildout.cfg
===================================================================
--- zope.repositorypolicy/trunk/buildout.cfg	                        (rev 0)
+++ zope.repositorypolicy/trunk/buildout.cfg	2010-03-05 15:08:06 UTC (rev 109677)
@@ -0,0 +1,8 @@
+[buildout]
+develop = .
+parts = egg 
+
+[egg]
+recipe = zc.recipe.egg
+eggs = zope.repositorypolicy
+interpreter = py

Added: zope.repositorypolicy/trunk/setup.py
===================================================================
--- zope.repositorypolicy/trunk/setup.py	                        (rev 0)
+++ zope.repositorypolicy/trunk/setup.py	2010-03-05 15:08:06 UTC (rev 109677)
@@ -0,0 +1,27 @@
+from setuptools import setup, find_packages
+
+setup(
+    name='zope.repositorypolicy',
+    version='0.1dev',
+    author='Zope Developers',
+    author_email='zope-dev at zope.org',
+    url='http://pypi.python.org/pypi/zope.repositorypolicy',
+    description="""\
+        Tools to verify and help sustain policy compliance for projects in
+        svn.zope.org
+    """,
+    packages=find_packages('src'),
+    package_dir={'': 'src'},
+    include_package_data=True,
+    zip_safe=False,
+    license='ZPL 2.1',
+    namespace_packages=['zope'],
+    install_requires=[
+        'setuptools',
+        'subvertpy'],
+    entry_points="""
+        [console_scripts]
+        zope-org-check-repos = zope.repositorypolicy.repository:main
+        zope-org-check-project = zope.repositorypolicy.project:main
+        zope-org-fix-project = zope.repositorypolicy.copyright:main
+    """)


Property changes on: zope.repositorypolicy/trunk/setup.py
___________________________________________________________________
Added: svn:eol-style
   + native

Added: zope.repositorypolicy/trunk/src/zope/__init__.py
===================================================================
--- zope.repositorypolicy/trunk/src/zope/__init__.py	                        (rev 0)
+++ zope.repositorypolicy/trunk/src/zope/__init__.py	2010-03-05 15:08:06 UTC (rev 109677)
@@ -0,0 +1 @@
+__import__('pkg_resources').declare_namespace(__name__)


Property changes on: zope.repositorypolicy/trunk/src/zope/__init__.py
___________________________________________________________________
Added: svn:eol-style
   + native

Added: zope.repositorypolicy/trunk/src/zope/repositorypolicy/__init__.py
===================================================================
--- zope.repositorypolicy/trunk/src/zope/repositorypolicy/__init__.py	                        (rev 0)
+++ zope.repositorypolicy/trunk/src/zope/repositorypolicy/__init__.py	2010-03-05 15:08:06 UTC (rev 109677)
@@ -0,0 +1 @@
+# Make this a Python package


Property changes on: zope.repositorypolicy/trunk/src/zope/repositorypolicy/__init__.py
___________________________________________________________________
Added: svn:eol-style
   + native

Added: zope.repositorypolicy/trunk/src/zope/repositorypolicy/copyright.py
===================================================================
--- zope.repositorypolicy/trunk/src/zope/repositorypolicy/copyright.py	                        (rev 0)
+++ zope.repositorypolicy/trunk/src/zope/repositorypolicy/copyright.py	2010-03-05 15:08:06 UTC (rev 109677)
@@ -0,0 +1,34 @@
+# Copyright (c) 2010 Zope Foundation and Contributors
+# See also LICENSE.txt
+
+import sys
+import zope.repositorypolicy.project
+import StringIO
+
+
+class FixCopyrightHeaders(object):
+    """A simple helper to fix source file copyright headers."""
+
+    def __init__(self, working_dir, owner):
+        self.working_dir = working_dir
+        self.owner = owner
+
+    def run(self):
+        zope.repositorypolicy.project.walk_project_dir(
+            self.working_dir, self._fix_file)
+
+    def _fix_file(self, path):
+        print path
+        output = StringIO.StringIO()
+        for line in open(path):
+            m = zope.repositorypolicy.project.COPYRIGHT_PATTERN.match(line)
+            if m is not None:
+                line = '%sCopyright (c) %s %s%s' % (
+                    m.group('lead'), m.group('periods'), self.owner,
+                    m.group('tail'))
+            output.write(line)
+        open(path, 'w').write(output.getvalue())
+
+
+def main():
+    FixCopyrightHeaders(sys.argv[1], sys.argv[2]).run()


Property changes on: zope.repositorypolicy/trunk/src/zope/repositorypolicy/copyright.py
___________________________________________________________________
Added: svn:eol-style
   + native

Added: zope.repositorypolicy/trunk/src/zope/repositorypolicy/data/ZPL-2.1.txt
===================================================================
--- zope.repositorypolicy/trunk/src/zope/repositorypolicy/data/ZPL-2.1.txt	                        (rev 0)
+++ zope.repositorypolicy/trunk/src/zope/repositorypolicy/data/ZPL-2.1.txt	2010-03-05 15:08:06 UTC (rev 109677)
@@ -0,0 +1,44 @@
+Zope Public License (ZPL) Version 2.1
+
+A copyright notice accompanies this license document that identifies the
+copyright holders.
+
+This license has been certified as open source. It has also been designated as
+GPL compatible by the Free Software Foundation (FSF).
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions in source code must retain the accompanying copyright
+notice, this list of conditions, and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the accompanying copyright
+notice, this list of conditions, and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+3. Names of the copyright holders must not be used to endorse or promote
+products derived from this software without prior written permission from the
+copyright holders.
+
+4. The right to distribute this software or to use it for any purpose does not
+give you the right to use Servicemarks (sm) or Trademarks (tm) of the
+copyright
+holders. Use of them is covered by separate agreement with the copyright
+holders.
+
+5. If any files are modified, you must cause the modified files to carry
+prominent notices stating that you changed the files and the date of any
+change.
+
+Disclaimer
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


Property changes on: zope.repositorypolicy/trunk/src/zope/repositorypolicy/data/ZPL-2.1.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: zope.repositorypolicy/trunk/src/zope/repositorypolicy/project.py
===================================================================
--- zope.repositorypolicy/trunk/src/zope/repositorypolicy/project.py	                        (rev 0)
+++ zope.repositorypolicy/trunk/src/zope/repositorypolicy/project.py	2010-03-05 15:08:06 UTC (rev 109677)
@@ -0,0 +1,122 @@
+# Copyright (c) 2010 Zope Foundation and Contributors
+# See also LICENSE.txt
+
+import sys
+import os
+import os.path
+import subprocess
+import re
+
+COPYRIGHT_PATTERN = re.compile(
+    '^(?P<lead>.*)Copyright \\(c\\) '
+    '(?P<periods>[0-9\-, ]+) (?P<owner>.*?)(?P<tail>\W*)$')
+
+
+def walk_project_dir(root, callback):
+    def visit(args, dirname, names):
+        for name in list(names):
+            if name.startswith('.'):
+                names.remove(name)
+                continue
+            if name.endswith('.egg-info'):
+                names.remove(name)
+                continue
+            if os.path.splitext(name)[1] in [
+                    '.so', '.pyc', '.pyo']:
+                continue
+            if os.path.isfile(os.path.join(dirname, name)):
+                path = os.path.join(dirname, name)
+                callback(path)
+    os.path.walk(root, visit, ())
+
+
+class Checker(object):
+
+    data_dir = os.path.join(os.path.dirname(__file__), 'data')
+    license_name = 'ZPL 2.1'
+    copyright_holder = 'Zope Foundation and Contributors'
+
+    def __init__(self, working_dir):
+        self.working_dir = working_dir
+        self.log = []
+
+    def run(self):
+        self.check_license_file()
+        self.check_egg_metadata()
+        self.check_copyright()
+
+    def check_license_file(self):
+        """Verifies license expression:
+
+            - the file LICENSE.txt exists and has a valid copy of the ZPL 2.1
+            - the file setup.py (if it exists) and is marked as ZPL 2.1
+
+        """
+        license = os.path.join(self.working_dir, 'LICENSE.txt')
+        if not os.path.isfile(license):
+            self.log.append('LICENSE.txt: Missing license file')
+        else:
+            license_content = open(license).read()
+            license_expected = open(
+                os.path.join(self.data_dir, 'ZPL-2.1.txt')).read()
+            if license_content != license_expected:
+                self.log.append('LICENSE.txt: Not a valid copy of ZPL 2.1')
+
+    def check_egg_metadata(self):
+        setup = os.path.join(self.working_dir, 'setup.py')
+        if os.path.isfile(setup):
+            s = subprocess.Popen([sys.executable, setup,
+                                  '--license', '--author'],
+                                 stdout=subprocess.PIPE)
+            s.wait()
+            metadata = s.stdout.readlines()
+            license = metadata[0].strip()
+            if license != self.license_name:
+                self.log.append(
+                    'setup.py: license not declared as "%s" (found: "%s")' %
+                    (self.license_name, license))
+            author = metadata[1].strip()
+            if author != self.copyright_holder:
+                self.log.append(
+                    'setup.py: author not declared as "%s" '
+                    '(found: "%s")' %
+                    (self.copyright_holder, author))
+
+    def check_copyright(self):
+        """Verifies the copyright assignment to the Zope Foundation
+
+            - the file COPYRIGHT.txt exists and has correct content
+            - all copyright statements that can be found refer to the Zope
+              foundation
+
+        """
+        copyright = os.path.join(self.working_dir, 'COPYRIGHT.txt')
+        if not os.path.isfile(copyright):
+            self.log.append('COPYRIGHT.txt: Missing copyright file')
+        else:
+            content = open(copyright).read().strip()
+            if content != self.copyright_holder:
+                self.log.append(
+                    'COPYRIGHT.txt: not assigned to Zope Foundation '
+                    '(found: "%s")' % content)
+        walk_project_dir(self.working_dir, self._check_copyright_file)
+
+    def _check_copyright_file(self, filename):
+        for i, line in enumerate(open(filename)):
+            m = COPYRIGHT_PATTERN.match(line)
+            if m is None:
+                continue
+            if m.group('owner') != self.copyright_holder:
+                self.log.append('%s:%i: incorrect copyright holder: %s' % (
+                    filename.replace(self.working_dir + '/', ''), i + 1,
+                    m.group('owner')))
+
+
+def main():
+    result = 0
+    checker = Checker(sys.argv[1])
+    checker.run()
+    for entry in checker.log:
+        result = 1
+        print entry
+    sys.exit(result)


Property changes on: zope.repositorypolicy/trunk/src/zope/repositorypolicy/project.py
___________________________________________________________________
Added: svn:eol-style
   + native

Added: zope.repositorypolicy/trunk/src/zope/repositorypolicy/repository.py
===================================================================
--- zope.repositorypolicy/trunk/src/zope/repositorypolicy/repository.py	                        (rev 0)
+++ zope.repositorypolicy/trunk/src/zope/repositorypolicy/repository.py	2010-03-05 15:08:06 UTC (rev 109677)
@@ -0,0 +1,63 @@
+# Copyright (c) 2010 Zope Foundation and Contributors
+# See also LICENSE.txt
+
+import os
+import re
+import shutil
+import subvertpy.client
+import subvertpy.ra
+import tempfile
+import zope.repositorypolicy.project
+
+
+RELEASE_BRANCH = re.compile(r'^[0-9]+\.[0-9]+$')
+
+
+class Checker(object):
+
+    root = 'svn://svn.zope.org/repos/main'
+
+    def __init__(self):
+        self.repos = subvertpy.ra.RemoteAccess(self.root)
+
+    def run(self):
+        for project, branch in self.list_projects_branches():
+            working_dir = tempfile.mkdtemp()
+            os.chdir(working_dir)
+            try:
+                c = subvertpy.client.Client()
+                c.checkout(url='%s/%s/%s' % (self.root, project, branch),
+                           path=working_dir, rev='HEAD')
+                checker = zope.repositorypolicy.project.Checker(working_dir)
+                checker.run()
+                for entry in checker.log:
+                    yield '%s/%s:%s' % (project, branch, entry)
+            finally:
+                shutil.rmtree(working_dir)
+
+    def list_projects_branches(self):
+        for project in self.repos.get_dir('/')[0].keys():
+            top = self.repos.get_dir(project)[0].keys()
+            if 'trunk' in top:
+                yield project, 'trunk'
+            if 'branches' in top:
+                branches = self.repos.get_dir(
+                    '%s/branches' % project)[0].keys()
+                releases = []
+                for branch in branches:
+                    if not RELEASE_BRANCH.match(branch):
+                        continue
+                    releases.append([int(x) for x in branch.split('.')])
+                releases.sort()
+                for release in releases[-2:]:
+                    release = '.'.join(str(x) for x in release)
+                    yield project, 'branches/%s' % release
+
+
+def main():
+    result = 0
+    checker = Checker()
+    for entry in checker.run():
+        result = 1
+        print entry
+    sys.exit(result)


Property changes on: zope.repositorypolicy/trunk/src/zope/repositorypolicy/repository.py
___________________________________________________________________
Added: svn:eol-style
   + native



More information about the checkins mailing list