root/releases/pkgcore/0.2.5/setup.py @ ferringb%2540gmail.com-20070216163631-f8g17lmpamn34hk9

Revision ferringb%2540gmail.com-20070216163631-f8g17lmpamn34hk9, 12.8 kB (checked in by Brian Harring <ferringb@…>, 21 months ago)

add NEWS into the released tarball

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