Review Board

beta

Make Djblets installable as a Python egg

Updated 4 months, 2 weeks ago

Christian Hammond Reviewers
trunk reviewboard
None Navi
This change allows Djblets to be built as a Python egg, meaning that down the road users will be able to install it directly using easy_install and that it will automatically be downloaded when other programs (such as Review Board) are easy_install'd.

This is the first step in making Review Board installable as an egg.
Tested that I could build eggs and source distributions and that the files expected were there.

Diff revision 1 (Latest)

  1. /trunk/djblets/MANIFEST.in: 1 change [ new content ]
  2. /trunk/djblets/ez_setup.py: 1 change [ new content ]
  3. /trunk/djblets/setup.py: 7 changes [ 1 2 3 4 5 6 7 ]
  4. /trunk/djblets/setup.cfg: 1 change [ new content ]
/trunk/djblets/MANIFEST.in
New File
1
recursive-include djblets *.txt *.html *.css *.js *.htc
/trunk/djblets/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/djblets/setup.py
Revision 11835 New Change
1
#!/usr/bin/env python
1
#!/usr/bin/env python
2
#
2
#
3
# setup.py -- Installation for djblets
3
# setup.py -- Installation for djblets
4
#
4
#
5
# Copyright (C) 2007 David Trowbridge
5
# Copyright (C) 2008 Christian Hammond
6
# Copyright (C) 2007-2008 David Trowbridge
6
#
7
#
7
# This program is free software; you can redistribute it and/or
8
# This program is free software; you can redistribute it and/or
8
# modify it under the terms of the GNU General Public License
9
# modify it under the terms of the GNU General Public License
9
# as published by the Free Software Foundation; either version 2
10
# as published by the Free Software Foundation; either version 2
10
# of the License, or (at your option) any later version.
11
# of the License, or (at your option) any later version.
17
# You should have received a copy of the GNU General Public License
18
# You should have received a copy of the GNU General Public License
18
# along with this program; if not, write to the Free Software
19
# along with this program; if not, write to the Free Software
19
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20
#
21
#
21
22
22
from distutils.core import setup
23
from ez_setup import use_setuptools
24
use_setuptools()
23
25
24
setup(name='djblets',
26
from setuptools import setup, find_packages
25
      version='0.1',
26
      packages=['djblets', 'djblets.auth', 'djblets.util'])
27
27
28
29
VERSION = "0.4"
30
31
32
setup(name="Djblets",
33
      version=VERSION,
34
      license="MIT",
35
      description="A collection of useful classes and functions for Django",
36
      packages=find_packages(),
37
      install_requires=['Django>=1.0-beta-1'],
38
      include_package_data=True,
39
      zip_safe=False,
40
      maintainer="Christian Hammond",
41
      maintainer_email="chipx86@chipx86.com",
42
      url="http://www.review-board.org/wiki/Djblets",
43
      classifiers=[
44
          "Development Status :: 4 - Beta",
45
          "Environment :: Web Environment",
46
          "Framework :: Django",
47
          "Intended Audience :: Developers",
48
          "License :: OSI Approved :: MIT License",
49
          "Operating System :: OS Independent",
50
          "Programming Language :: Python",
51
          "Topic :: Software Development",
52
          "Topic :: Software Development :: Libraries :: Python Modules",
53
      ]
54
)
/trunk/djblets/setup.cfg
New File
1
[egg_info]
2
tag_build = .dev
3
tag_svn_revision = 1
  1. /trunk/djblets/MANIFEST.in: 1 change [ new content ]
  2. /trunk/djblets/ez_setup.py: 1 change [ new content ]
  3. /trunk/djblets/setup.py: 7 changes [ 1 2 3 4 5 6 7 ]
  4. /trunk/djblets/setup.cfg: 1 change [ new content ]