root/releases/pkgcore/0.2.3/setup.py @ ferringb%2540gmail.com-20070210234636-2igvbv3qzdu1igsd

Revision ferringb%2540gmail.com-20070210234636-2igvbv3qzdu1igsd, 12.8 kB (checked in by Brian Harring <ferringb@…>, 22 months ago)

make --debug drop -DNDEBUG

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