Initial work at removing the root Makefile. Ugly setup.py. Probably not worth it... no-makefiles
authorW. Trevor King <wking@drexel.edu>
Sun, 6 Mar 2011 01:18:20 +0000 (20:18 -0500)
committerW. Trevor King <wking@drexel.edu>
Sun, 6 Mar 2011 01:18:20 +0000 (20:18 -0500)
MANIFEST.in [new file with mode: 0644]
doc/install.txt
setup.py

diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644 (file)
index 0000000..dd5e5b2
--- /dev/null
@@ -0,0 +1,6 @@
+include AUTHORS COPYING NEWS README test.py
+include doc/*.txt
+include doc/*.py
+include doc/man/*.txt
+recursive-include interfaces *
+recursive-include misc *
index c428087d314d2a588f9616bbba5c2a7b855ad1fb..350f87fa78cb1a8f816376458e6f6581fa005a83 100644 (file)
@@ -29,37 +29,11 @@ BE is available as a Git repository::
 
     $ git clone git://gitorious.org/be/be.git be
 
-See the homepage_ for details.  If you do branch the Git repo, you'll
-need to run::
+See the homepage_ for details.  To install the checkout, run the
+standard::
 
-    $ make
+    $ python setup.py install
 
-to build some auto-generated files (e.g. :mod:`libbe._version`), and::
-
-    $ make install
-
-to install BE.  By default BE will install into your home directory,
-but you can tweak the ``PREFIX`` variable in ``Makefile`` to install
-to another location.
-
-By default, ``make`` builds both a man page for ``be`` and the HTML
-Sphinx documentation (:doc:`doc`).  You can customize the
-documentation targets by overriding_ the ``DOC`` variable.  For
-example, to disable all documentation during a build/install, run::
-
-    $ make DOC= install
-
-Note that ``setup.py`` (called during ``make install``) will install
-the man page (``doc/man/be.1``) if it exists, so::
-
-    $ make
-    $ make DOC= install
-
-*will* build (first ``make``) install (second ``make``) the man page.
-
-
-.. _homepage: http://bugseverywhere.org/
-.. _overriding: http://www.gnu.org/software/make/manual/html_node/Overriding.html#Overriding
 
 
 Release tarballs
index b7fb8396f6b0c2493358af44f663c8b52f1d5ef5..eaef3cb0dd11c46c169eccb078aea5a84b086ae2 100755 (executable)
--- a/setup.py
+++ b/setup.py
 #!/usr/bin/env python
 
-from distutils.core import setup
+from distutils.core import setup, Command
+from distutils.command.build import build
+from distutils.command.build_py import build_py
+from distutils.command.install import install
+from distutils import log
+import os
 import os.path
+import sys
 
-from libbe import _version
+try:
+    import docutils
+    import docutils.core
+except ImportError, e:
+    log.warn(
+        'cannot import docutils (required to build documentation): %s' % e)
+    docutils = None
 
-rev_id = _version.version_info["revision"]
-rev_date = _version.version_info["date"]
+try:
+    import sphinx
+except ImportError, e:
+    log.warn('cannot import sphinx (required to build user guide): %s' % e)
+    sphinx = None
 
-data_files = []
+from libbe.version import version
+from libbe.util.subproc import invoke
+
+
+_this_dir = os.path.dirname(__file__)
+
+
+class _build_py (build_py):
+    def run(self):
+        target_dir = os.path.join(self.build_lib, 'libbe')
+        if os.path.exists('.git'):
+            self._generate_version(target_dir)
+        # distutils uses old-style classes, so no super()
+        build_py.run(self)
+
+    def _generate_version(self, target_dir):
+        version_path = os.path.join(target_dir, '_version.py')
+        log.info('generate %s using git' % version_path)
+        if not self.dry_run:
+            format = (
+                '"Autogenerated by make libbe/_version.py"%n'
+                'version_info = {%n'
+                '    "date":"%cd",%n'
+                '    "revision":"%H",%n'
+                '    "committer":"%cn"}%n'
+                )
+            status,stdout,stderr = invoke(
+                ['git', 'log', '-1', '--date=short',
+                 "--pretty='format:%s'" % format])
+
+
+class build_doc (Command):
+    description = "build package documentation"
+
+    user_options = [
+        ('man', None, 'compile man page (with docutils) [default]'),
+        ('no-man', None, "don't compile man page"),
+        ('guide', None, 'compile user guide (with sphinx) [default]'),
+        ('no-guide', None, "don't compile user guide"),
+        ]
+
+    boolean_options = ['man', 'guide']
+    negative_opt = {'no-man': 'man', 'no-guide': 'guide'}
+
+    def initialize_options(self):
+        self.man = True
+        self.guide = True
+
+    def finalize_options(self):
+        pass
+
+    def run(self):
+        if self.man:
+            self._build_man()
+        if self.guide:
+            self._build_guide()
+
+    def _build_man(self):
+        if docutils == None:
+            log.error('cannot build man page without docutils')
+            return
+        man_dir = os.path.join(_this_dir, 'doc', 'man')
+        for filename in os.listdir(man_dir):
+            basename,extension = os.path.splitext(filename)
+            if extension == '.txt':
+                source_path = os.path.join(man_dir, filename)
+                destination_path = os.path.join(man_dir, basename)
+                log.info('converting %s -> %s' % (source_path, destination_path))
+                if not self.dry_run:
+                    docutils.core.publish_file(
+                        source_path=source_path,
+                        destination_path=destination_path,
+                        writer_name='manpage')
+
+    def _build_guide(self):
+        if docutils == None:
+            log.error('cannot build user guide without docutils')
+            return
+        if sphinx == None:
+            log.error('cannot build user guide without sphinx')
+            return
+        log.info('building user guide')
+        doc_dir = os.path.join(_this_dir, 'doc')
+        doctree_dir = os.path.join(doc_dir, '.build', 'doctrees')
+        html_dir = os.path.join(doc_dir, '.build', 'html')
+        log.info('generating autodoc/automodule pages for API documentation')
+        if not self.dry_run:
+            cwd = os.getcwd()
+            try:
+                os.chdir(doc_dir)
+                status,stdout,stderr = invoke(
+                    [sys.executable, 'generate-libbe-txt.py'])
+            finally:
+                os.chdir(cwd)
+        log.info('building user guide with sphinx')
+        if not self.dry_run:
+            ret = sphinx.main([
+                    'sphinx-build', '-d', doctree_dir,
+                    '-b', 'html', doc_dir, html_dir])
+            if ret != 0:
+                log.error('errors building user guide')
+
+
+build.sub_commands.append(('build_doc', None))
+
+
+class install_doc (Command):
+    description = "install package documentation"
+
+    user_options = [
+        ('install-dir=', 'd',
+         "base directory for installing doc files "
+         "(default: installation base dir)"),
+        ('root=', None,
+         "install everything relative to this alternate root directory"),
+        ('man', None, 'install man page [default]'),
+        ('no-man', None, "don't install man page"),
+        ('man-dir=', None, 'man page installation directory'),
+        ('guide', None, 'install user guide [default]'),
+        ('no-guide', None, "don't install user guide"),
+        ('guide-dir=', None, 'guide installation directory'),
+        ]
+
+    boolean_options = ['man', 'guide']
+    negative_opt = {'no-man': 'man', 'no-guide': 'guide'}
+
+    def initialize_options(self):
+        self.install_dir = None
+        self.root = None
+        self.man = True
+        self.man_dir = None
+        self.guide = True
+        self.guide_dir = None
+        self.outfiles = []
+
+    def finalize_options(self):
+        self.set_undefined_options('install',
+                                   ('install_data', 'install_dir'),
+                                   ('root', 'root'),
+                                   )
+        if not self.man_dir:
+            self.man_dir = os.path.join(
+                self.install_dir, 'share', 'man')
+        if not self.guide_dir:
+            self.guide_dir = os.path.join(
+                self.install_dir, 'share', 'doc', 'be')
+
+    def run(self):
+        if self.man:
+            self._install_man()
+        if self.guide:
+            self._install_guide()
+
+    def _install_man(self):
+        if docutils == None:
+            log.error('cannot build man page without docutils')
+            return
+        man_dir = os.path.join(_this_dir, 'doc', 'man')
+        for filename in os.listdir(man_dir):
+            basename,extension = os.path.splitext(filename)
+            if extension == '.txt':
+                man_path = os.path.join(man_dir, basename)
+                if not os.path.exists(man_path):
+                    log.warn('expected man page %s not found' % man_path)
+                    continue
+                page,dot_section = os.path.splitext(basename)
+                section = dot_section.lstrip('.')
+                section_dir = os.path.join(self.man_dir, 'man%s' % section)
+                outfile = os.path.join(section_dir, basename)
+                self.mkpath(section_dir)
+                self.copy_file(infile=man_path, outfile=outfile)
+                self.outfiles.append(outfile)
+
+    def _install_guide(self):
+        return
+        if docutils == None:
+            log.error('cannot build user guide without docutils')
+            return
+        if sphinx == None:
+            log.error('cannot build user guide without sphinx')
+            return
+        log.info('building user guide')
+        doc_dir = os.path.join(_this_dir, 'doc')
+        doctree_dir = os.path.join(doc_dir, '.build', 'doctrees')
+        html_dir = os.path.join(doc_dir, '.build', 'html')
+        log.info('generating autodoc/automodule pages for API documentation')
+        if not self.dry_run:
+            cwd = os.getcwd()
+            try:
+                os.chdir(doc_dir)
+                status,stdout,stderr = invoke(
+                    [sys.executable, 'generate-libbe-txt.py'])
+            finally:
+                os.chdir(cwd)
+        log.info('building user guide with sphinx')
+        if not self.dry_run:
+            ret = sphinx.main([
+                    'sphinx-build', '-d', doctree_dir,
+                    '-b', 'html', doc_dir, html_dir])
+            if ret != 0:
+                log.error('errors building user guide')
+
+
+            # add an entry to data_files
+            data_files.append(('share/doc/be/html', [html_dir]))
+            log.info('data files: %s' % data_files)
+
+    def get_outputs(self):
+        return self.outfiles
+
+
+install.sub_commands.append(('install_doc', None))
 
-man_path = os.path.join('doc', 'man', 'be.1')
-if os.path.exists(man_path):
-    data_files.append(('share/man/man1', [man_path]))
 
 setup(
     name='Bugs Everywhere',
-    version=rev_date,
+    version=version(),
+    maintainer='Chris Ball',
+    maintainer_email='be-devel@bugseverywhere.org',
     description='Bugtracker supporting distributed revision control',
+    long_description=open(os.path.join(_this_dir, 'README'), 'r').read(),
     url='http://bugseverywhere.org/',
+    license='GNU GPLv2',
     packages=['libbe',
               'libbe.command',
               'libbe.storage',
@@ -28,5 +255,7 @@ setup(
               'libbe.ui.util',
               'libbe.util'],
     scripts=['be'],
-    data_files=data_files,
+    data_files=[],
+    cmdclass={'build_py': _build_py, 'build_doc': build_doc,
+              'install_doc': install_doc},
     )