root/masterdriverz/pkgcore-dev/setup.py @ ferringb%2540gmail.com-20080812233613-hseskuavtb5nbw0u

Revision ferringb%2540gmail.com-20080812233613-hseskuavtb5nbw0u, 14.5 kB (checked in by Brian Harring <ferringb@…>, 3 months ago)

python2.4 behaviour diff between it and 2.5; 2.5 accepts None to os.path.join; 2.4 doesn't

Line 
1#!/usr/bin/env python
2
3import os
4import sys
5import errno
6import subprocess
7import unittest
8
9from distutils import core, ccompiler, log, errors
10from distutils.command import (build, sdist, build_py, build_ext,
11    build_scripts, install)
12from stat import ST_MODE
13
14
15def write_bzr_verinfo(destination):
16    log.info('generating bzr_verinfo')
17    f = open(destination, 'w')
18    try:
19        if subprocess.call(['bzr', 'version-info', '--format=python'],
20                           stdout=f):
21            raise errors.DistutilsExecError('bzr version-info failed')
22        # HACK: insert the current tag, if possible.
23        try:
24            from bzrlib import branch, errors as ebzr
25        except ImportError:
26            log.warn('cannot import bzrlib trying to determine tag')
27            return
28
29        try:
30            b = branch.Branch.open_containing(__file__)[0]
31        except ebzr.NotBranchError, e:
32            log.warn('not a branch (%s) trying to determine tag' % (e,))
33            return
34
35        if b.supports_tags():
36            tags = b.tags.get_reverse_tag_dict().get(b.last_revision())
37            if tags:
38                f.write("version_info['tags'] = %r\n" % (tags,))
39
40    finally:
41        f.close()
42
43class mysdist(sdist.sdist):
44
45    """sdist command specifying the right files and generating ChangeLog."""
46
47    user_options = sdist.sdist.user_options + [
48        ('build-docs', None, 'build docs [default]'),
49        ('no-build-docs', None, 'do not build docs'),
50        ('changelog', None, 'create a ChangeLog [default]'),
51        ('changelog-start=', None, 'start rev to dump the changelog from,'
52            ' defaults to 1'),
53        ('no-changelog', None, 'do not create the ChangeLog file'),
54        ]
55
56    boolean_options = sdist.sdist.boolean_options + ['changelog'] + ['build-docs']
57
58    negative_opt = {'no-changelog': 'changelog', 'no-build-docs':'build-docs'}
59    negative_opt.update(sdist.sdist.negative_opt)
60
61    default_format = dict(sdist.sdist.default_format)
62    default_format["posix"] = "bztar"
63
64    def initialize_options(self):
65        sdist.sdist.initialize_options(self)
66        self.changelog = True
67        self.changelog_start = None
68        self.build_docs = True
69
70    def get_file_list(self):
71        """Get a filelist without doing anything involving MANIFEST files."""
72        # This is copied from the "Recreate manifest" bit of sdist.
73        self.filelist.findall()
74        if self.use_defaults:
75            self.add_defaults()
76
77        # This bit is roughly equivalent to a MANIFEST.in template file.
78        for key, globs in self.distribution.package_data.iteritems():
79            for pattern in globs:
80                self.filelist.include_pattern(os.path.join(key, pattern))
81
82        self.filelist.append("AUTHORS")
83        self.filelist.append("COPYING")
84        self.filelist.append("NEWS")
85
86        self.filelist.include_pattern('.[ch]', prefix='src')
87
88        for prefix in ['doc', 'dev-notes', 'man']:
89            self.filelist.include_pattern('.rst', prefix=prefix)
90            self.filelist.exclude_pattern(os.path.sep + 'index.rst',
91                                          prefix=prefix)
92        self.filelist.append('build_docs.py')
93        self.filelist.append(os.path.join('man', 'manpage.py'))
94        self.filelist.include_pattern('*', prefix='examples')
95        self.filelist.include_pattern('*', prefix='bin')
96
97        if self.prune:
98            self.prune_file_list()
99
100        # This is not optional: remove_duplicates needs sorted input.
101        self.filelist.sort()
102        self.filelist.remove_duplicates()
103
104    def make_release_tree(self, base_dir, files):
105        """Create and populate the directory tree that is put in source tars.
106
107        This copies or hardlinks "normal" source files that should go
108        into the release and adds generated files that should not
109        exist in a working tree.
110        """
111        sdist.sdist.make_release_tree(self, base_dir, files)
112        if self.build_docs:
113            if subprocess.call(['./build_docs.py'], cwd=base_dir):
114                raise errors.DistutilsExecError("build_docs failed")
115        if self.changelog:
116            args = []
117            if self.changelog_start:
118                args = ['-r', '%s..-1' % self.changelog_start]
119            log.info("regenning ChangeLog (may take a while)")
120            if subprocess.call(
121                ['bzr', 'log', '--verbose'] + args,
122                stdout=open(os.path.join(base_dir, 'ChangeLog'), 'w')):
123                raise errors.DistutilsExecError('bzr log failed')
124        write_bzr_verinfo(os.path.join(base_dir, 'pkgcore', 'bzr_verinfo.py'))
125        for base, dirs, files in os.walk(base_dir):
126            for x in files:
127                if x.endswith(".pyc") or x.endswith(".pyo"):
128                    os.unlink(os.path.join(base, x))
129
130
131class pkgcore_build_scripts(build_scripts.build_scripts):
132
133    """Build (modify #! line) the pwrapper_installed script."""
134
135    def finalize_options(self):
136        build_scripts.build_scripts.finalize_options(self)
137        self.scripts = [os.path.join('bin', 'pwrapper_installed')]
138
139# pkgcore_{build,install}_scripts are registered as separate commands
140# instead of overriding the default {build,install}_scripts because
141# those are only run if the "scripts" arg to setup is not empty.
142
143build.build.sub_commands.append(('pkgcore_build_scripts', None))
144
145
146class pkgcore_install_scripts(core.Command):
147
148    """Install symlinks to the pwrapper_installed script.
149
150    Adapted from distutils install_scripts.
151    """
152
153    user_options = [
154        ('install-dir=', 'd', "directory to install scripts to"),
155        ('build-dir=','b', "build directory (where to install from)"),
156        ('force', 'f', "force installation (overwrite existing files)"),
157        ('skip-build', None, "skip the build steps"),
158        ]
159
160    boolean_options = ['force', 'skip-build']
161
162    def initialize_options(self):
163        self.install_dir = None
164        self.force = 0
165        self.build_dir = None
166        self.skip_build = None
167
168    def finalize_options(self):
169        self.set_undefined_options('build', ('build_scripts', 'build_dir'))
170        self.set_undefined_options('install',
171                                   ('install_scripts', 'install_dir'),
172                                   ('force', 'force'),
173                                   ('skip_build', 'skip_build'),
174                                   )
175        self.scripts = [
176            path for path in os.listdir('bin')
177            if path not in ('pwrapper', 'pwrapper_installed')]
178
179    def run(self):
180        if not self.skip_build:
181            self.run_command('pkgcore_build_scripts')
182        self.mkpath(self.install_dir)
183        if os.name == 'posix':
184            # Copy the wrapper once.
185            copyname = os.path.join(self.install_dir, self.scripts[0])
186            self.copy_file(os.path.join(self.build_dir, 'pwrapper_installed'),
187                           copyname)
188            # Set the executable bits (owner, group, and world).
189            if self.dry_run:
190                log.info("changing mode of %s", copyname)
191            else:
192                mode = ((os.stat(copyname)[ST_MODE]) | 0555) & 07777
193                log.info("changing mode of %s to %o", copyname, mode)
194                os.chmod(copyname, mode)
195            # Use symlinks for the other scripts.
196            for script in self.scripts[1:]:
197                # We do not use self.copy_file(link='sym') because we
198                # want to make a relative link and copy_file requires
199                # the "source" to be an actual file.
200                dest = os.path.join(self.install_dir, script)
201                log.info('symlinking %s to %s', dest, self.scripts[0])
202                try:
203                    os.symlink(self.scripts[0], dest)
204                except (IOError, OSError), e:
205                    if e.errno != errno.EEXIST:
206                        raise
207                    os.remove(dest)
208                    os.symlink(self.scripts[0], dest)
209        else:
210            # Just copy all the scripts.
211            for script in self.scripts:
212                self.copy_file(
213                    os.path.join(self.build_dir, 'pwrapper_installed'),
214                    os.path.join(self.install_dir, script))
215
216    def get_inputs(self):
217        return self.scripts
218
219    def get_outputs(self):
220        return self.scripts
221
222
223class pkgcore_install_man(core.Command):
224
225    """Install man pages"""
226
227
228    def initialize_options(self):
229        self.install_man = None
230        self.prefix = None
231        self.man_pages = []
232
233    def finalize_options(self):
234        self.set_undefined_options('install',
235                                   ('root', 'install_man'),
236                                   ('install_base', 'prefix'),
237                                   )
238        if not self.install_man:
239            self.install_man = '/'
240        self.install_man = os.path.join(self.install_man,
241            self.prefix.lstrip(os.path.sep), 'share', 'man')
242        self.man_pages = [
243            os.path.join(os.getcwd(), 'man', path) for path in os.listdir('man')
244            if len(path) > 2 and path[-2] == '.' and path[-1].isdigit()]
245
246
247    def run(self):
248        for x in sorted(set(page[-1] for page in self.man_pages)):
249            self.mkpath(os.path.join(self.install_man, 'man%s' % x))
250
251        for page in self.man_pages:
252            self.copy_file(
253                page,
254                os.path.join(self.install_man, 'man%s' % page[-1],
255                    os.path.basename(page)))
256
257    def get_inputs(self):
258        return self.man_pages
259
260    def get_outputs(self):
261        return self.man_pages
262
263
264install.install.sub_commands.append(('pkgcore_install_scripts', None))
265install.install.sub_commands.append(('pkgcore_install_man', None))
266
267
268class pkgcore_build_ext(build_ext.build_ext):
269
270    def build_extensions(self):
271        if self.debug:
272            # say it with me kids... distutils sucks!
273            for x in ("compiler_so", "compiler", "compiler_cxx"):
274                setattr(self.compiler, x,
275                    [y for y in getattr(self.compiler, x) if y != '-DNDEBUG'])
276        return build_ext.build_ext.build_extensions(self)
277
278
279
280class pkgcore_build_py(build_py.build_py):
281
282    def run(self):
283        build_py.build_py.run(self)
284        bzr_ver = self.get_module_outfile(
285            self.build_lib, ('pkgcore',), 'bzr_verinfo')
286        if not os.path.exists(bzr_ver):
287            try:
288                write_bzr_verinfo(bzr_ver)
289            except errors.DistutilsExecError:
290                # Not fatal, just less useful --version output.
291                log.warn('generating bzr_verinfo failed!')
292            else:
293                self.byte_compile([bzr_ver])
294
295        fp = os.path.join(self.build_lib, "pkgcore", "bin", "ebuild-helpers")
296        for f in os.listdir(fp):
297            self.set_chmod(os.path.join(fp, f))
298        fp = os.path.join(self.build_lib, "pkgcore", "bin", "ebuild-env")
299        for f in ("ebuild.sh", "ebuild-daemon.sh"):
300            self.set_chmod(os.path.join(fp, f))
301
302    def set_chmod(self, path):
303        if self.dry_run:
304            log.info("changing mode of %s", path)
305        else:
306            mode = ((os.stat(path)[ST_MODE]) | 0555) & 07777
307            log.info("changing mode of %s to %o", path, mode)
308            os.chmod(path, mode)
309
310
311
312class TestLoader(unittest.TestLoader):
313
314    """Test loader that knows how to recurse packages."""
315
316    def loadTestsFromModule(self, module):
317        """Recurses if module is actually a package."""
318        paths = getattr(module, '__path__', None)
319        tests = [unittest.TestLoader.loadTestsFromModule(self, module)]
320        if paths is None:
321            # Not a package.
322            return tests[0]
323        for path in paths:
324            for child in os.listdir(path):
325                if (child != '__init__.py' and child.endswith('.py') and
326                    child.startswith('test')):
327                    # Child module.
328                    childname = '%s.%s' % (module.__name__, child[:-3])
329                else:
330                    childpath = os.path.join(path, child)
331                    if not os.path.isdir(childpath):
332                        continue
333                    if not os.path.exists(os.path.join(childpath,
334                                                       '__init__.py')):
335                        continue
336                    # Subpackage.
337                    childname = '%s.%s' % (module.__name__, child)
338                tests.append(self.loadTestsFromName(childname))
339        return self.suiteClass(tests)
340
341
342testLoader = TestLoader()
343
344
345class test(core.Command):
346
347    """Run our unit tests in a built copy.
348
349    Based on code from setuptools.
350    """
351
352    user_options = []
353
354    def initialize_options(self):
355        # Options? What options?
356        pass
357
358    def finalize_options(self):
359        # Options? What options?
360        pass
361
362    def run(self):
363        build_ext = self.reinitialize_command('build_ext')
364        build_ext.inplace = True
365        self.run_command('build_ext')
366        # Somewhat hackish: this calls sys.exit.
367        unittest.main('pkgcore.test', argv=['setup.py', '-v'], testLoader=testLoader)
368
369
370packages = [
371    root.replace(os.path.sep, '.')
372    for root, dirs, files in os.walk('pkgcore')
373    if '__init__.py' in files]
374
375extra_flags = ['-Wall']
376
377from pkgcore.const import VERSION
378core.setup(
379    name='pkgcore',
380    version=VERSION,
381    description='package managing framework',
382    url='http://www.pkgcore.org/',
383    license='GPL-2',
384    packages=packages,
385    package_data={
386        'pkgcore': [
387            'bin/ebuild-env/*',
388            'bin/ebuild-helpers/*',
389            ],
390        },
391    ext_modules=[
392        core.Extension(
393            'pkgcore.ebuild._atom', ['src/atom.c'],
394            extra_compile_args=extra_flags),
395        core.Extension(
396            'pkgcore.ebuild._cpv', ['src/cpv.c'],
397            extra_compile_args=extra_flags),
398        core.Extension(
399            'pkgcore.ebuild._depset', ['src/depset.c'],
400            extra_compile_args=extra_flags),
401        core.Extension(
402            'pkgcore.ebuild._filter_env', [
403                'src/filter_env.c', 'src/bmh_search.c'],
404            extra_compile_args=extra_flags),
405        core.Extension(
406            'pkgcore.ebuild._misc', ['src/misc.c'],
407            extra_compile_args=extra_flags),
408        core.Extension(
409            'pkgcore.restrictions._restrictions', ['src/restrictions.c'],
410            extra_compile_args=extra_flags),
411        ],
412    cmdclass={
413        'sdist': mysdist,
414        'build_py': pkgcore_build_py,
415        'build_ext': pkgcore_build_ext,
416        'test': test,
417        'pkgcore_build_scripts': pkgcore_build_scripts,
418        'pkgcore_install_scripts': pkgcore_install_scripts,
419        'pkgcore_install_man': pkgcore_install_man,
420        },
421    )
Note: See TracBrowser for help on using the browser.