Review Board

beta

Make Review Board installable as a Python egg

Updated 4 months, 2 weeks ago

Christian Hammond Reviewers
trunk reviewboard
None Review Board SVN
This provides the ability to build a Python egg for Review Board. It contains all the information needed to register in the Cheese Shop, a list of dependencies, and all the files.

This is not fully complete and it's not ready for people to use, but I need to get this part in before I can finish. It's step two in my master plan.

After this, I'll be setting up the buildbots to build eggs for all our dependencies and dropping them in a snapshots directory. They will then be installed and tested against the packages as part of the builds to ensure that all the eggs are complete.

Once a night, when the eggs are complete, the info will be put available on our Downloads page and Review Board and Djblets eggs will be automatically uploaded to the Cheese Shop, tagged as SVN snapshots.

Users will then be able to either download the eggs or just 'easy_install ReviewBoard'. Djblets will be automatically downloaded and, once I have the build setup going, we'll be able to host an unofficial Django Evolution snapshot on a page pointed to by the Review Board setup.py, causing it to look in our install if it's not available in the Cheese Shop.

We'll be able to take advantage of how setuptools handles versioning in the future so that users will by default grab the stable releases when using easy_install while still having the option to specify that they want the bleeding edge nightly snapshots.
Tested that I could build a ReviewBoard egg and that it appeared to have all the files we care about without bundling our dependencies.
/trunk/reviewboard/MANIFEST.in
New File
1
include AUTHORS
2
include COPYING
3
include INSTALL
4
include MANIFEST.in
5
include NEWS
6
include README
7
include settings_local.py.tmpl
8
recursive-include accounts/fixtures *
9
recursive-include admin/fixtures *
10
recursive-include contrib *
11
recursive-include diffviewer/testdata *
12
recursive-include htdocs *.css *.htc *.png *.jpg *.gif *.js
13
recursive-include locale *
14
recursive-include reviews/fixtures *
15
recursive-include scmtools/fixtures *
16
recursive-include scmtools/testdata *
17
recursive-include templates *.html *.txt
/trunk/reviewboard/__init__.py
Revision 1446 New Change
1
# The version of Review Board.
1
# The version of Review Board.
2
VERSION = "0.4-pre"
2
VERSION = "0.9"
/trunk/reviewboard/ez_setup.py
New File
1
#!python
2
"""Bootstrap setuptools installation
3
4
If you want to use setuptools in your package's setup.py, just include this
5
file in the same directory with it, and add this to the top of your setup.py::
6
7
    from ez_setup import use_setuptools
8
    use_setuptools()
9
10
If you want to require a specific version of setuptools, set a download
11
mirror, or use an alternate download directory, you can do so by supplying
12
the appropriate options to ``use_setuptools()``.
13
14
This file can also be run as a script to install or upgrade setuptools.
15
"""
16
import sys
17
DEFAULT_VERSION = "0.6c8"
18
DEFAULT_URL     = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3]
19
20
md5_data = {
21
    'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca',
22
    'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb',
23
    'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b',
24
    'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a',
25
    'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618',
26
    'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac',
27
    'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5',
28
    'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4',
29
    'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c',
30
    'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b',
31
    'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27',
32
    'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277',
33
    'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa',
34
    'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e',
35
    'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e',
36
    'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f',
37
    'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2',
38
    'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc',
39
    'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167',
40
    'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64',
41
    'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d',
42
    'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20',
43
    'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab',
44
    'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53',
45
    'setuptools-0.6c7-py2.3.egg': '209fdf9adc3a615e5115b725658e13e2',
46
    'setuptools-0.6c7-py2.4.egg': '5a8f954807d46a0fb67cf1f26c55a82e',
47
    'setuptools-0.6c7-py2.5.egg': '45d2ad28f9750e7434111fde831e8372',
48
    'setuptools-0.6c8-py2.3.egg': '50759d29b349db8cfd807ba8303f1902',
49
    'setuptools-0.6c8-py2.4.egg': 'cba38d74f7d483c06e9daa6070cce6de',
50
    'setuptools-0.6c8-py2.5.egg': '1721747ee329dc150590a58b3e1ac95b',
51
}
52
53
import sys, os
54
55
def _validate_md5(egg_name, data):
56
    if egg_name in md5_data:
57
        from md5 import md5
58
        digest = md5(data).hexdigest()
59
        if digest != md5_data[egg_name]:
60
            print >>sys.stderr, (
61
                "md5 validation of %s failed!  (Possible download problem?)"
62
                % egg_name
63
            )
64
            sys.exit(2)
65
    return data
66
67
68
def use_setuptools(
69
    version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
70
    download_delay=15
71
):
72
    """Automatically find/download setuptools and make it available on sys.path
73
74
    `version` should be a valid setuptools version number that is available
75
    as an egg for download under the `download_base` URL (which should end with
76
    a '/').  `to_dir` is the directory where setuptools will be downloaded, if
77
    it is not already available.  If `download_delay` is specified, it should
78
    be the number of seconds that will be paused before initiating a download,
79
    should one be required.  If an older version of setuptools is installed,
80
    this routine will print a message to ``sys.stderr`` and raise SystemExit in
81
    an attempt to abort the calling script.
82
    """
83
    was_imported = 'pkg_resources' in sys.modules or 'setuptools' in sys.modules
84
    def do_download():
85
        egg = download_setuptools(version, download_base, to_dir, download_delay)
86
        sys.path.insert(0, egg)
87
        import setuptools; setuptools.bootstrap_install_from = egg
88
    try:
89
        import pkg_resources
90
    except ImportError:
91
        return do_download()       
92
    try:
93
        pkg_resources.require("setuptools>="+version); return
94
    except pkg_resources.VersionConflict, e:
95
        if was_imported:
96
            print >>sys.stderr, (
97
            "The required version of setuptools (>=%s) is not available, and\n"
98
            "can't be installed while this script is running. Please install\n"
99
            " a more recent version first, using 'easy_install -U setuptools'."
100
            "\n\n(Currently using %r)"
101
            ) % (version, e.args[0])
102
            sys.exit(2)
103
        else:
104
            del pkg_resources, sys.modules['pkg_resources']    # reload ok
105
            return do_download()
106
    except pkg_resources.DistributionNotFound:
107
        return do_download()
108
109
def download_setuptools(
110
    version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
111
    delay = 15
112
):
113
    """Download setuptools from a specified location and return its filename
114
115
    `version` should be a valid setuptools version number that is available
116
    as an egg for download under the `download_base` URL (which should end
117
    with a '/'). `to_dir` is the directory where the egg will be downloaded.
118
    `delay` is the number of seconds to pause before an actual download attempt.
119
    """
120
    import urllib2, shutil
121
    egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3])
122
    url = download_base + egg_name
123
    saveto = os.path.join(to_dir, egg_name)
124
    src = dst = None
125
    if not os.path.exists(saveto):  # Avoid repeated downloads
126
        try:
127
            from distutils import log
128
            if delay:
129
                log.warn("""
130
---------------------------------------------------------------------------
131
This script requires setuptools version %s to run (even to display
132
help).  I will attempt to download it for you (from
133
%s), but
134
you may need to enable firewall access for this script first.
135
I will start the download in %d seconds.
136
137
(Note: if this machine does not have network access, please obtain the file
138
139
   %s
140
141
and place it in this directory before rerunning this script.)
142
---------------------------------------------------------------------------""",
143
                    version, download_base, delay, url
144
                ); from time import sleep; sleep(delay)
145
            log.warn("Downloading %s", url)
146
            src = urllib2.urlopen(url)
147
            # Read/write all in one block, so we don't create a corrupt file
148
            # if the download is interrupted.
149
            data = _validate_md5(egg_name, src.read())
150
            dst = open(saveto,"wb"); dst.write(data)
151
        finally:
152
            if src: src.close()
153
            if dst: dst.close()
154
    return os.path.realpath(saveto)
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
def main(argv, version=DEFAULT_VERSION):
192
    """Install or upgrade setuptools and EasyInstall"""
193
    try:
194
        import setuptools
195
    except ImportError:
196
        egg = None
197
        try:
198
            egg = download_setuptools(version, delay=0)
199
            sys.path.insert(0,egg)
200
            from setuptools.command.easy_install import main
201
            return main(list(argv)+[egg])   # we're done here
202
        finally:
203
            if egg and os.path.exists(egg):
204
                os.unlink(egg)
205
    else:
206
        if setuptools.__version__ == '0.0.1':
207
            print >>sys.stderr, (
208
            "You have an obsolete version of setuptools installed.  Please\n"
209
            "remove it from your system entirely before rerunning this script."
210
            )
211
            sys.exit(2)
212
213
    req = "setuptools>="+version
214
    import pkg_resources
215
    try:
216
        pkg_resources.require(req)
217
    except pkg_resources.VersionConflict:
218
        try:
219
            from setuptools.command.easy_install import main
220
        except ImportError:
221
            from easy_install import main
222
        main(list(argv)+[download_setuptools(delay=0)])
223
        sys.exit(0) # try to force an exit
224
    else:
225
        if argv:
226
            from setuptools.command.easy_install import main
227
            main(argv)
228
        else:
229
            print "Setuptools version",version,"or greater has been installed."
230
            print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
231
232
def update_md5(filenames):
233
    """Update our built-in md5 registry"""
234
235
    import re
236
    from md5 import md5
237
238
    for name in filenames:
239
        base = os.path.basename(name)
240
        f = open(name,'rb')
241
        md5_data[base] = md5(f.read()).hexdigest()
242
        f.close()
243
244
    data = ["    %r: %r,\n" % it for it in md5_data.items()]
245
    data.sort()
246
    repl = "".join(data)
247
248
    import inspect
249
    srcfile = inspect.getsourcefile(sys.modules[__name__])
250
    f = open(srcfile, 'rb'); src = f.read(); f.close()
251
252
    match = re.search("\nmd5_data = {\n([^}]+)}", src)
253
    if not match:
254
        print >>sys.stderr, "Internal error!"
255
        sys.exit(2)
256
257
    src = src[:match.start(1)] + repl + src[match.end(1):]
258
    f = open(srcfile,'w')
259
    f.write(src)
260
    f.close()
261
262
263
if __name__=='__main__':
264
    if len(sys.argv)>2 and sys.argv[1]=='--md5update':
265
        update_md5(sys.argv[2:])
266
    else:
267
        main(sys.argv[1:])
268
269
270
271
272
/trunk/reviewboard/setup.py
New File
1
#!/usr/bin/env python
2
#
3
# Setup script for Review Board.
4
#
5
# A big thanks to Django project for some of the fixes used in here for
6
# MacOS X and data files installation.
7
8
import os
9
import re
10
import sys
11
12
from ez_setup import use_setuptools
13
use_setuptools()
14
15
from setuptools import setup, find_packages
16
from distutils.command.install_data import install_data
17
from distutils.command.install import INSTALL_SCHEMES
18
19
from __init__ import VERSION # Ick.
20
21
22
# Make sure we're actually in the directory containing setup.py.
23
root_dir = os.path.dirname(__file__)
24
25
if root_dir != "":
26
    os.chdir(root_dir)
27
28
29
# Tell distutils to put the data_files in platform-specific installation
30
# locations. See here for an explanation:
31
# http://groups.google.com/group/comp.lang.python/browse_thread/thread/35ec7b2fed36eaec/2105ee4d9e8042cb
32
for scheme in INSTALL_SCHEMES.values():
33
    scheme['data'] = scheme['purelib']
34
35
36
class osx_install_data(install_data):
37
    # On MacOS, the platform-specific lib dir is
38
    # /System/Library/Framework/Python/.../
39
    # which is wrong. Python 2.5 supplied with MacOS 10.5 has an
40
    # Apple-specific fix for this in distutils.command.install_data#306. It
41
    # fixes install_lib but not install_data, which is why we roll our own
42
    # install_data class.
43
44
    def finalize_options(self):
45
        # By the time finalize_options is called, install.install_lib is
46
        # set to the fixed directory, so we set the installdir to install_lib.
47
        # The # install_data class uses ('install_data', 'install_dir') instead.
48
        self.set_undefined_options('install', ('install_lib', 'install_dir'))
49
        install_data.finalize_options(self)
50
51
if sys.platform == "darwin":
52
    cmdclasses = {'install_data': osx_install_data}
53
else:
54
    cmdclasses = {'install_data': install_data}
55
56
57
# Since we don't actually keep our directories in a reviewboard directory
58
# like we really should, we have to fake it. Prepend "reviewboard." here,
59
# set package_dir below, and make sure to exclude our svn:externals
60
# dependencies.
61
packages = [
62
    "reviewboard." + package_name
63
    for package_name in find_packages(exclude=["djblets", "djblets.*",
64
                                               "django_evolution",
65
                                               "django_evolution.*"])
66
]
67
68
69
# Build the reviewboard package.
70
setup(name="ReviewBoard",
71
      version=VERSION,
72
      license="MIT",
73
      description="Review Board, a web-based code review tool",
74
      url="http://www.review-board.org/",
75
      author="The Review Board Project",
76
      author_email="reviewboard@googlegroups.com",
77
      maintainer="Christian Hammond",
78
      maintainer_email="chipx86@chipx86.com",
79
      packages=packages,
80
      package_dir={'reviewboard': ''},
81
      cmdclass=cmdclasses,
82
      install_requires=['Django>=1.0-beta-1', 'django_evolution', 'Djblets'],
83
      include_package_data=True,
84
      zip_safe=False,
85
      classifiers=[
86
          "Development Status :: 4 - Beta",
87
          "Environment :: Web Environment",
88
          "Framework :: Django",
89
          "Intended Audience :: Developers",
90
          "License :: OSI Approved :: MIT License",
91
          "Natural Language :: English",
92
          "Operating System :: OS Independent",
93
          "Programming Language :: Python",
94
          "Topic :: Software Development",
95
          "Topic :: Software Development :: Quality Assurance",
96
      ]
97
)
/trunk/reviewboard/setup.cfg
New File
1
[egg_info]
2
tag_build = .dev
3
tag_svn_revision = 1
  1. /trunk/reviewboard/MANIFEST.in: 1 change [ new content ]
  2. /trunk/reviewboard/__init__.py: 1 change [ 1 ]
  3. /trunk/reviewboard/ez_setup.py: 1 change [ new content ]
  4. /trunk/reviewboard/setup.py: 1 change [ new content ]
  5. /trunk/reviewboard/setup.cfg: 1 change [ new content ]