Commits

Ronald Oussoren committed f8a1bbc

Getting there...

* All documentation files are now part of the output tree

* Slight restructuring of the source code

* 'html' subcommand can call 'collect' using a command-line option

Not happy about the L&F of the side, time to experiment with
Sphinx templates.

Comments (0)

Files changed (3)

 api
 dev
 tmp
+tutorials
 examples
 __pycache__
 
 in pure Python. See our tutorial for an example of this.
 
 Release information
-===================
+-------------------
 
-PyObjC 2.4 was released on November 1st, 2012.
+.. raw:: html
 
-The current development version is PyObjC 2.5b1
+   <p>PyObjC <span id="release_version">X.Y</span> was released on <span id="release_date">YYYY-MM-DD</span>.
+   See the <a href="core/changelog.html">changelog</a> for more information.
+   <script type="text/javascript">
+      $.getJSON('http://pypi.python.org/pypi/pyobjc/json?callback=?', function(data) {
+         $('#release_version').text(data.info.version);
+
+         $.each(data.urls, function(idx, info) {
+                $('#release_date').text(info.upload_time.substring(0, 10));
+         });
+      });
+   </script>
+
 
 General documentation
 =====================
    core/typemapping
    core/fsref-fsspec
    core/kvo
+   tutorials/index
    notes/quartz-vs-coregraphics
    examples/index
    apinotes
 
 
-API specification
+API documentation
 =================
 
 .. toctree::
 PyObjC Developement
 ===================
 
+PyObjC development is hosted at bickbucket, in particular at <https://bitbucket.org/ronaldoussoren/pyobjc/>.
+
+Important resources:
+
+* `Issue tracker <https://bitbucket.org/ronaldoussoren/pyobjc/issues>`_
+
+* `Repository browser <https://bitbucket.org/ronaldoussoren/pyobjc/src>`_
+
+* Creating a checkout of the respository:
+
+  .. sourcecode:: sh
+
+     $ hg clone https://bitbucket.org/ronaldoussoren/pyobjc pyobjc
+
+  You can then use the "install.py" at the root of the checkout to
+  install this version of PyObjC.
+
 .. toctree::
    :maxdepth: 1
    :glob:
 into this tree.
 
 TODO:
-* Finish this far enough to be actually build the website
+* Tweak templates/layout to taste
 
-* Tweak templates/layout to taste
+* Add 'upload' command
 
 * When that works: make packages.python.org/pyobjc* redirect
   to the documentation site (because this will add a "package documenation"
 import os
 import re
 import shutil
-import shutil
 import zipfile
 import argparse
 import subprocess
 # All paths in the document map are
 # relative to the root of the pyobjc
 # tree
+MY_DIR = os.path.dirname(__file__)
 
 API_NOTES_INTRODUCTION=textwrap.dedent("""\
     Introduction
     ('pyobjc-core/NEWS.txt',                            'core/changelog.rst'),
     ('pyobjc-core/Doc/index.rst',                       None),
     ('pyobjc-core/Doc/Makefile',                        None),
+    ('pyobjc-core/Doc/xcode.rst',                       None), # XXX: ignored because documentation is out of date
     ('pyobjc-core/Doc/intro.rst',                       'core/intro.rst'),
     ('pyobjc-core/Doc/blocks.rst',                      'core/blocks.rst'),
     ('pyobjc-core/Doc/typemapping.rst',                 'core/typemapping.rst'),
     ('pyobjc-core/Doc/dev/index.rst',                   None),
     (RE(r'^pyobjc-core/Doc/sphinx_build/.*'),           None),
     (RE(r'^pyobjc-core/Doc/lib/(?P<name>.*)'),          'api/{name}'),
+    (RE(r'^pyobjc-core/Doc/tutorials/(?P<name>.*)'),    'tutorials/{name}'),
     (RE(r'^pyobjc-core/Doc/dev/(?P<name>.*)'),          'dev/{name}'),
+    ('pyobjc-framework-Cocoa/Doc/AppCategories.txt',    'api/module-PyObjCTools.AppCategories.rst'),
+    ('pyobjc-framework-Cocoa/Doc/FndCategories.txt',    'api/module-PyObjCTools.FndCategories.rst'),
+    ('pyobjc-framework-Cocoa/Doc/NEWS.txt',             None),
+    ('pyobjc-framework-Cocoa/Doc/threading-helpers.txt','api/threading-helpers.rst'),
+    ('pyobjc-framework-QTKit/Doc/changelog.txt',        None),
+    ('pyobjc-framework-Quartz/Doc/context-managers.txt', 'api/coregraphics-context-managers.rst'),
 
     # Collect all API notes at a generic location
     (RE(r'^pyobjc-framework-(?P<subdir>[^/]*)/Doc/api-notes-(?P<framework>.*).txt$'),  'apinotes/{framework}.rst'),
 def parse_arguments():
     parser = argparse.ArgumentParser(prog="pyobjc-website")
     parser.add_argument("--verbose", action="store_true", help="print progress information", default=False)
+    parser.add_argument("--source-root", help="Path to the PyObjC source tree", metavar="DIR", default="../pyobjc")
 
     subparsers = parser.add_subparsers(dest="command")
     
     collect_cmd = subparsers.add_parser("collect", help="Collect data from pyobjc source tree")
-    collect_cmd.add_argument("--source-root", help="Path to the PyObjC source tree", metavar="DIR", default="../pyobjc")
 
     html_cmd = subparsers.add_parser("html", help="Build HTML tree")
+    html_cmd.add_argument("--update", dest="html_update", action="store_true", help="update source before build", default=False)
+
+    html_cmd = subparsers.add_parser("show", help="Show HTML in browser")
+    cleanup_cmd = subparsers.add_parser("cleanup", help="Remove HTML tree and collected documentation")
 
     args = parser.parse_args()
-    if not hasattr(args, "command"):
+    if not hasattr(args, "command") or args.command is None:
         # Regression in python3: subcommand's aren't required anymore???
         parser.print_usage(file=sys.stderr)
         print("pyobjc-website: error: too few arguments", file=sys.stderr)
         with open(path, "w") as fp:
             fp.write(data)
 
-def main():
-    args = parse_arguments()
-    my_dir = os.path.dirname(__file__)
+def action_collect(args):
+    if args.verbose:
+        print("* Collecting documentation files")
 
-    if args.command == 'collect':
-        if not os.path.exists(args.source_root):
-            print("Source directory '{}' does not exist".format(args.source_root), file=sys.stderr)
-            sys.exit(1)
+    if not os.path.exists(args.source_root):
+        print("Source directory '{}' does not exist".format(args.source_root), file=sys.stderr)
+        sys.exit(1)
 
-        collect_documents(args.source_root, my_dir, args.verbose)
-        fixup_apinotes(my_dir, args.verbose)
-        collect_examples(args.source_root, my_dir, args.verbose)
-        
-    elif args.command == 'html':
-        import conf
-        
-        if args.verbose:
-            extra_args = []
-        else:
-            extra_args = ['-q']
-        
-        if not sys.stderr.isatty():
-            extra_args.append('-N')
+    collect_documents(args.source_root, MY_DIR, args.verbose)
+    fixup_apinotes(MY_DIR, args.verbose)
+    collect_examples(args.source_root, MY_DIR, args.verbose)
 
-        subprocess.check_call(["sphinx-build", "-b", "html", "-d", "_build/doctrees" ] + extra_args + [ my_dir, os.path.join(my_dir, "_build/html")],
-                cwd=my_dir)
+def action_cleanup(args):
+    if args.verbose:
+        print("* Cleaning up generated files")
 
-        # sphinx doesn't copy zipfiles into the output tree, do
-        # this manually
-    #    topdir = os.path.join(my_dir, 'examples')
-    #    for dirpath, dirnames, filenames in os.walk(topdir):
-    #        for fn in filenames:
-    #            if fn.endswith('.zip'):
-    #                input_file = os.path.join(dirpath, fn)
-    #                output_file = os.path.join('_build', 'html', 'examples', dirpath[len(topdir)+1:], fn)
-#
-#                    if args.verbose:
-#                        print("Copy {} into HTML tree".format(input_file))
-#
-##                    shutil.copy(input_file, output_file)
+    for subdir in ('_build', 'api', 'apinotes', 'core', 'dev', 'tutorials', 'examples'):
+        subdir = os.path.join(MY_DIR, subdir)
+        if os.path.exists(subdir):
+            if args.verbose:
+                print("Remove directory: {}".format(subdir))
+                shutil.rmtree(subdir)
 
-        # slightly tweak the HTML for the example pages, I haven't found yet if/how I
-        # can accomplish this through regular sphinx mechanisms
-        for dirpath, dirnames, filenames in os.walk(os.path.join(my_dir, '_build', 'html', 'examples')):
-            for fn in filenames:
-                if not fn.endswith('.html'): continue
-                fn = os.path.join(dirpath, fn)
+def action_show(args):
+    if args.verbose:
+        print("* Show HTML in browser")
 
-                with open(fn, 'rU') as fp:
-                    data_in = fp.read()
+    subprocess.call(['/usr/bin/open', os.path.join(MY_DIR, '_build', 'html', 'index.html')])
 
-                data_out = data_in.replace(
+def action_html(args):
+    import conf
+
+    if args.html_update:
+        action_collect(args)
+
+    if args.verbose:
+        print("* Generate HTML files")
+    
+    if args.verbose:
+        extra_args = []
+    else:
+        extra_args = ['-q']
+    
+    if not sys.stderr.isatty():
+        extra_args.append('-N')
+
+    subprocess.check_call(["sphinx-build", "-b", "html", "-d", "_build/doctrees" ] + extra_args + [ MY_DIR, os.path.join(MY_DIR, "_build/html")],
+            cwd=MY_DIR)
+
+    # slightly tweak the HTML for the example pages, I haven't found yet if/how I
+    # can accomplish this through regular sphinx mechanisms
+    for dirpath, dirnames, filenames in os.walk(os.path.join(MY_DIR, '_build', 'html', 'examples')):
+        for fn in filenames:
+            if not fn.endswith('.html'): continue
+            fn = os.path.join(dirpath, fn)
+
+            with open(fn, 'rU') as fp:
+                data_in = fp.read()
+
+            data_out = data_in.replace(
 '''<div class="tabber section" id="sources">
 <h2>Sources</h2>''',
 '''<h2>Sources</h2>
 <div class="tabber section" id="sources">''')
-                if data_out != data_in:
-                    if args.verbose:
-                        print("Fix-up {}".format(fn))
-                    with open(fn, 'w') as fp:
-                        fp.write(data_out)
+            if data_out != data_in:
+                if args.verbose:
+                    print("Fix-up {}".format(fn))
+                with open(fn, 'w') as fp:
+                    fp.write(data_out)
 
+def main():
+    args = parse_arguments()
 
-        sys.exit(0)
+    if args.command == 'collect':
+        action_collect(args)
+
+    elif args.command == 'cleanup':
+        action_cleanup(args)
+
+    elif args.command == 'show':
+        action_show(args)
+
+    elif args.command == 'html':
+        action_html(args)
 
     else:
         raise RuntimeError("Unhandled command: {}".format(args.command))