root/releases/pkgcore/0.2.6/setup.py @ marienz%2540gentoo.org-20070304030024-71oi4xir3g4p85ve

Revision marienz%2540gentoo.org-20070304030024-71oi4xir3g4p85ve, 13.1 kB (checked in by Marien Zwart <marienz@…>, 21 months ago)

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