Skip to content

Commit

Permalink
Updated docs site to work with the new setup.
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobian committed Oct 11, 2010
1 parent 5744132 commit f63e29c
Show file tree
Hide file tree
Showing 11 changed files with 156 additions and 129 deletions.
1 change: 1 addition & 0 deletions djangodocs/fixtures/initial_data.json
Expand Up @@ -5,6 +5,7 @@
"fields": {
"lang": "en",
"version": "dev",
"scm": "svn",
"scm_url": "http://code.djangoproject.com/svn/django/trunk/docs",
"is_default": false
}
Expand Down
3 changes: 3 additions & 0 deletions djangodocs/fixtures/releases.json
Expand Up @@ -5,6 +5,7 @@
"fields": {
"lang": "en",
"version": "1.0",
"scm": "svn",
"scm_url": "http://code.djangoproject.com/svn/django/branches/releases/1.0.X/docs",
"is_default": false
}
Expand All @@ -15,6 +16,7 @@
"fields": {
"lang": "en",
"version": "1.1",
"scm": "svn",
"scm_url": "http://code.djangoproject.com/svn/django/branches/releases/1.1.X/docs",
"is_default": false
}
Expand All @@ -25,6 +27,7 @@
"fields": {
"lang": "en",
"version": "1.2",
"scm": "svn",
"scm_url": "http://code.djangoproject.com/svn/django/trunk/docs",
"is_default": true
}
Expand Down
66 changes: 26 additions & 40 deletions djangodocs/management/commands/update_docs.py
Expand Up @@ -2,47 +2,33 @@
Update and build the documentation into files for display with the djangodocs
app.
"""
from __future__ import absolute_import

import os
import sys
import pysvn
import sphinx
import subprocess
from django.conf import settings
from django.core.management.base import NoArgsCommand
from unipath import FSPath as Path
from ...models import DocumentRelease

SVN_DOCS_TRUNK = 'http://code.djangoproject.com/svn/django/trunk/docs/'
SVN_DOCS_RELEASES = 'http://code.djangoproject.com/svn/django/branches/releases/'
class Command(NoArgsCommand):
def handle_noargs(self, **kwargs):
for release in DocumentRelease.objects.all():
print "Updating %s..." % release
destdir = Path(settings.DOCS_BUILD_ROOT).child(release.lang, release.version)
if not destdir.exists():
destdir.mkdir(parents=True)

# Make an SCM checkout/update into the destination directory.
# Do this dynamically in case we add other SCM later.
getattr(self, 'update_%s' % release.scm)(release.scm_url, destdir)

svn = pysvn.Client()
# Run Sphinx by faking a commandline. Better than shelling out, I s'pose.
subprocess.call(['sphinx-build',
'-b', 'json', # Use the JSON builder
'-q', # Be vewy qwiet
destdir, # Source file directory
destdir.child('_build', 'json'), # Destination directory
])

def get_doc_versions():
"""
Get a list of (lang, version, svnurl) tuples of docs to build.
"""
yield ('en', 'dev', SVN_DOCS_TRUNK)
for release in svn.ls(SVN_DOCS_RELEASES):
version = release.name.split('/')[-1].replace('.X', '')
yield ('en', version, "%s/docs/" % release.name)

def update_docs(basedir):
"""
Update all versions of the docs into the given base directory.
"""
for (lang, version, svnurl) in get_doc_versions():

# Make an SVN checkout (or update) in the destination directory,
# creating it if it doesn't exist
destdir = os.path.join(basedir, lang, version)
if not os.path.exists(destdir):
os.makedirs(destdir)
svn.checkout(svnurl, destdir)

# Run Sphinx by faking a commandline. Better than shelling out, I s'pose.
sphinx.main([
'sphinx-build', # Fake argv[0]
'-b', 'json', # Use the JSON builder
'-q', # Be vewy qwiet
destdir, # Source file directory
os.path.join(destdir, '_build', 'json'), # Destination directory
])

if __name__ == '__main__':
update_docs(sys.argv[1])
def update_svn(self, url, destdir):
subprocess.call(['svn', 'checkout', url, destdir])
16 changes: 15 additions & 1 deletion djangodocs/models.py
Expand Up @@ -6,8 +6,17 @@ def default(self):
return DocumentRelease.objects.get(is_default=True)

class DocumentRelease(models.Model):
"""
A "release" of documentation -- i.e. English for v1.2.
"""
SVN = 'svn'
SCM_CHOICES = (
(SVN, 'SVN'),
)

lang = models.CharField(max_length=2, choices=settings.LANGUAGES, default='en')
version = models.CharField(max_length=20)
scm = models.CharField(max_length=10, choices=SCM_CHOICES)
scm_url = models.URLField()
is_default = models.BooleanField()

Expand All @@ -16,8 +25,13 @@ class DocumentRelease(models.Model):
def __unicode__(self):
return "%s/%s" % (self.lang, self.version)

@models.permalink
def get_absolute_url(self):
return ('document-index', [], {'lang': self.lang, 'version': self.version})

def save(self, *args, **kwargs):
# There can be only one. Default, that is.
if self.is_default:
DocumentRelease.objects.update(is_default=False)
super(DocumentRelease, self).save(*args, **kwargs)
super(DocumentRelease, self).save(*args, **kwargs)

18 changes: 13 additions & 5 deletions djangodocs/settings.py
Expand Up @@ -4,11 +4,19 @@
APPEND_SLASH = True
INSTALLED_APPS = ['djangodocs']
TEMPLATE_DIRS = [os.path.join(os.path.dirname(__file__), "templates")] + TEMPLATE_DIRS
TEMPLATE_CONTEXT_PROCESSORS = ['django.core.context_processors.request']
TEMPLATE_CONTEXT_PROCESSORS = [
"django.contrib.auth.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.request",
]

ROOT_URLCONF = 'djangodocs.urls'
CACHE_MIDDLEWARE_KEY_PREFIX = 'djangodocs'

DOCS_PICKLE_ROOT = "/home/djangodocs/"
DOCS_DEFAULT_LANGUAGE = 'en'
DOCS_DEFAULT_VERSION = '1.2'
DOCS_PREVIOUS_VERSIONS = ['1.0', '1.1']
# Where to store the build Sphinx docs.
if DEVELOPMENT_MODE:
DOCS_BUILD_ROOT = '/tmp/djangodocs'
else:
DOCS_BUILD_ROOT = "/home/djangodocs/"
2 changes: 1 addition & 1 deletion djangodocs/templates/docs/doc.html
Expand Up @@ -28,7 +28,7 @@
width: 18em;
}
</style>
<link rel="stylesheet" href="http://media.djangoproject.com/css/pygments.css" type="text/css" />
<link rel="stylesheet" href="{{ MEDIA_URL }}css/pygments.css" type="text/css" />
{% endblock %}

{% block billboard %}
Expand Down
52 changes: 25 additions & 27 deletions djangodocs/templatetags/docs.py
@@ -1,7 +1,9 @@
from __future__ import absolute_import

from django import template
from django.conf import settings
from unipath import FSPath as Path
from djangodocs.forms import SearchForm
from ..models import DocumentRelease
from ..utils import get_doc_root, get_doc_path

register = template.Library()

Expand All @@ -19,17 +21,25 @@ def search_form(context, search_form_id='search'):
def get_all_doc_versions(parser, token):
"""
Get a list of all versions of this document to link to.
Usage: {% get_all_doc_versions <docurl> as "varname" %}
"""
try:
tagname, docurl, as_, asvar = token.split_contents()
except ValueError:
raise template.TemplateSyntaxError("Usage: {% get_all_doc_versions <docurl> as <varname> %}")
return AllDocVersionsTag(template.Variable(docurl), asvar)
return AllDocVersionsTag.handle(parser, token)

class AllDocVersionsTag(template.Node):
@classmethod
def handle(cls, parser, token):
try:
tagname, docurl, as_, asvar = token.split_contents()
except ValueError:
raise template.TemplateSyntaxError("Usage: {% get_all_doc_versions <docurl> as <varname> %}")
return cls(docurl, asvar)

def __init__(self, docurl, asvar):
self.docurl = docurl
self.docurl = template.Variable(docurl)
self.asvar = asvar
# FIXME
self.lang = 'en'

def render(self, context):
try:
Expand All @@ -38,27 +48,15 @@ def render(self, context):
return ''

versions = []
docroot = Path(settings.DOCS_PICKLE_ROOT).child(settings.DOCS_DEFAULT_LANGUAGE)

# Look for each version of the docs.
versions_to_check = ['dev', settings.DOCS_DEFAULT_VERSION] + settings.DOCS_PREVIOUS_VERSIONS
for version in versions_to_check:
version_root = docroot.child(version, '_build', 'json')

# First try path/to/doc/index.fjson
bits = url.strip('/').split('/') + ['index.fjson']
doc = version_root.child(*bits)
if not doc.exists():
# Then try path/to/doc.fjson
bits = bits[:-2] + ['%s.fjson' % bits[-2]]
doc = version_root.child(*bits)
if not doc.exists():
# Neither exists, so try next.
continue

# If we fall through to here, then the doc exists, so note that fact.
versions.append(version)

for release in DocumentRelease.objects.all():
version_root = get_doc_root(release.lang, release.version)
if version_root.exists():
doc_path = get_doc_path(version_root, url)
if doc_path:
versions.append(release.version)

# Save the versions into the context
context[self.asvar] = versions

Expand Down
26 changes: 17 additions & 9 deletions djangodocs/urls.py
@@ -1,42 +1,50 @@
import djangodocs.views
from django.conf import settings
from django.conf.urls.defaults import *
from . import views

urlpatterns = patterns('',
url(
r'^$',
djangodocs.views.index,
views.index,
),
url(
r'^(?P<lang>[a-z-]+)/$',
djangodocs.views.language,
views.language,
),
url(
r'^(?P<lang>[a-z-]+)/(?P<version>[\w.-]+)/$',
djangodocs.views.document,
views.document,
{'url': ''},
name = 'document-index',
),
url(
r'^(?P<lang>[a-z-]+)/(?P<version>[\w.-]+)/search/$',
djangodocs.views.search,
views.search,
name = 'document-search',
),
url(
r'^(?P<lang>[a-z-]+)/(?P<version>[\w.-]+)/_objects/$',
djangodocs.views.objects_inventory,
views.objects_inventory,
name = 'objects-inv',
),
url(
r'^(?P<lang>[a-z-]+)/(?P<version>[\w.-]+)/_images/(?P<path>.*)$',
djangodocs.views.images,
views.images,
),
url(
r'^(?P<lang>[a-z-]+)/(?P<version>[\w.-]+)/_source/(?P<path>.*)$',
djangodocs.views.source,
views.source,
),
url(
r'^(?P<lang>[a-z-]+)/(?P<version>[\w.-]+)/(?P<url>[\w./-]*)/$',
djangodocs.views.document,
views.document,
name = 'document-detail',
),
)

if settings.DEBUG:
urlpatterns += patterns('',
url(r'^media/(?P<path>.*)$',
'django.views.static.serve',
{'document_root': settings.MEDIA_ROOT}),
)
32 changes: 32 additions & 0 deletions djangodocs/utils.py
@@ -0,0 +1,32 @@
from django.conf import settings
from django.http import Http404
from unipath import FSPath as Path

def get_doc_root(lang, version):
return Path(settings.DOCS_BUILD_ROOT).child(lang, version, "_build", "json")

def get_doc_root_or_404(lang, version):
docroot = get_doc_root(lang, version)
if not docroot.exists():
raise Http404(docroot)
return docroot

def get_doc_path(docroot, subpath):
# First look for <bits>/index.fpickle, then for <bits>.fpickle
bits = subpath.strip('/').split('/') + ['index.fjson']
doc = docroot.child(*bits)
if doc.exists():
return doc

bits = bits[:-2] + ['%s.fjson' % bits[-2]]
doc = docroot.child(*bits)
if doc.exists():
return doc

return None

def get_doc_path_or_404(docroot, subpath):
doc = get_doc_path(docroot, subpath)
if doc is None:
raise Http404(doc)
return doc

0 comments on commit f63e29c

Please sign in to comment.