From c07f2f2ff28d1ebfd27b77bd6e46b6009a637f8c Mon Sep 17 00:00:00 2001 From: "Paul J. Davis" Date: Sat, 5 Jun 2010 20:00:30 -0400 Subject: [PATCH] Making the website more pretty. --- doc/buildweb.py | 74 ++---- doc/config.rb | 2 + doc/css/index.sass | 74 ++++++ doc/css/style.sass | 173 +++++--------- doc/htdocs/configure.html | 147 ++++++------ doc/htdocs/css/index.css | 254 ++++++++++++++++++++ doc/htdocs/css/style.css | 341 +++++++++++++++------------ doc/htdocs/deploy.html | 45 ++-- doc/htdocs/design.html | 47 ++-- doc/htdocs/faq.html | 199 ++++++++-------- doc/htdocs/images/gunicorn.png | Bin 0 -> 1581 bytes doc/htdocs/images/large_gunicorn.png | Bin 0 -> 20879 bytes doc/htdocs/index.html | 124 +++++----- doc/htdocs/install.html | 47 ++-- doc/htdocs/news.html | 69 ++++-- doc/htdocs/run.html | 51 ++-- doc/site/configure.rst | 5 +- doc/site/deploy.rst | 7 +- doc/site/design.rst | 5 +- doc/site/faq.rst | 6 +- doc/site/index.rst | 57 ----- doc/site/install.rst | 5 +- doc/site/news.rst | 7 + doc/site/run.rst | 5 +- doc/sitemap_gen.py | 10 +- doc/templates/base.html | 19 +- doc/templates/doc.html | 2 + doc/templates/index.html | 25 +- 28 files changed, 1065 insertions(+), 735 deletions(-) create mode 100644 doc/css/index.sass create mode 100644 doc/htdocs/css/index.css create mode 100644 doc/htdocs/images/gunicorn.png create mode 100644 doc/htdocs/images/large_gunicorn.png delete mode 100644 doc/site/index.rst diff --git a/doc/buildweb.py b/doc/buildweb.py index c86ce6f3..c3ea05e1 100755 --- a/doc/buildweb.py +++ b/doc/buildweb.py @@ -90,14 +90,14 @@ class Page(object): basename, oldext = os.path.splitext(filename) oldext = oldext.lower()[1:] - converter = getattr(self, "convert_%s" % oldext, lambda x: x) + converter = getattr(self, "convert_%s" % oldext, lambda x: (None, x)) if "insert_settings" in self.headers: body = body % {"settings": self.format_settings()} - self.body = converter(body) + self.toc, self.body = converter(body) newext = self.headers.get('ext', '.html') self.target = os.path.join(tgt_path, "%s%s" % (basename, newext)) - + def url(self): path = self.target.split(conf.OUTPUT_PATH)[1].lstrip('/') return "/".join([self.site.url, path]) @@ -126,6 +126,7 @@ class Page(object): kwargs = { "conf": conf, + "toc": self.toc, "body": self.body, "url": self.url() } @@ -139,7 +140,21 @@ class Page(object): writer_name="html", settings_overrides=overrides ) - return parts['html_body'] + lines = parts['html_body'].splitlines() + + toppos, botpos = None, None + for idx, line in enumerate(lines): + if line.find("_TOC_TOP_") >= 0: + toppos = idx + elif line.find("_TOC_BOT_") >= 0: + botpos = idx + + if toppos is None or botpos is None: + return None, parts['html_body'] + + toc = lines[toppos+1:botpos] + body = lines[:toppos] + lines[botpos+1:] + return '\n'.join(toc), '\n'.join(body) def format_settings(self): currdir = os.path.dirname(__file__) @@ -149,10 +164,10 @@ class Page(object): for i, s in enumerate(guncfg.KNOWN_SETTINGS): if i == 0 or s.section != guncfg.KNOWN_SETTINGS[i-1].section: ret.append("%s\n%s\n\n" % (s.section, "+" * len(s.section))) - ret.append(self.fmt_setting2(s)) + ret.append(self.fmt_setting(s)) return ''.join(ret) - def fmt_setting2(self, s): + def fmt_setting(self, s): if callable(s.default): val = inspect.getsource(s.default) val = "\n".join(" %s" % l for l in val.splitlines()) @@ -179,53 +194,6 @@ class Page(object): out.append("") return "\n".join(out) - def fmt_setting(self, s): - out = [] - lines = s.desc.splitlines() - width = max(map(lambda x: len(x), lines)) - - if not callable(s.default): - val = '%s' % s.default - else: - val = '' - - if s.cli and s.meta: - args = ["%s %s" % (arg, s.meta) for arg in s.cli] - cli = ', '.join(args) - elif s.cli: - cli = ", ".join(s.cli) - else: - cli = "N/A" - - width = 80 - namelen = 20 - deflen = 20 - clilen = width - (namelen + deflen + 4) - - args = ("-" * namelen, "-" * deflen, "-" * clilen) - out.append("+%s+%s+%s+" % args) - - names = "| %s" % s.name - names += " " * (namelen - (len(s.name) + 2)) - names += " | %s" % val - names += " " * (deflen - (len(val) + 2)) - names += " | %s" % cli - names += " " * (clilen - (len(cli) + 1)) - names += "|" - out.append(names) - - out.append(out[0].replace("-", "=")) - - for l in lines: - l = l.rstrip("\n") - if len(l) < width: - l += " " * ((width - 2) - len(l)) - out.append("|%s|" % l) - out.append("+%s+" % ("-" * (width - 2))) - out.extend(["", ""]) - - return "\n".join(out) - def main(): Site().render() diff --git a/doc/config.rb b/doc/config.rb index f59cfad7..a2615bbe 100644 --- a/doc/config.rb +++ b/doc/config.rb @@ -1,6 +1,8 @@ +require 'ninesixty' # Require any additional compass plugins here. # Set this to the root of your project when deployed: http_path = "/" css_dir = "htdocs/css" sass_dir = "css" images_dir = "images" +preferred_syntax = :sass diff --git a/doc/css/index.sass b/doc/css/index.sass new file mode 100644 index 00000000..c9bd8e2f --- /dev/null +++ b/doc/css/index.sass @@ -0,0 +1,74 @@ +@import 960/grid +@import 960/text + +@import compass/css3 +@import compass/layout.scss +@import compass/utilities/general +@import compass/utilities/lists + +@import compass/reset + +// Index Layout + +$ninesixty-columns: 24 + +#container.landing + +grid-container + #menu, #header, div.blurb, #tutorial, #actions, #footer + +grid-unit-base + #menu, #header, #footer + +grid-width(24) + #actions + div.blurb + +grid-width(8) + #tutorial + +grid-width(16) + ++text + +a, a:visited, a:hover, a:active + color: #569633 + text-decoration: none + +#header + margin: 46px 0px + +#menu + margin-bottom: 23px + +border-bottom-radius(10px) + background-color: #959595 + text-align: right + div.logo + float: left + margin-left: 10px + padding-top: 3px + ul + display: inline + margin-right: 10px + +no-bullets + li + display: inline + padding: 0px 3px + a + font-size: 17px + color: white + +#footer + border-top: 1px solid #959595 + padding: 10px 0px + text-align: center + color: #959595 + p + margin-bottom: 5px + +pre, tt + font-family: 'Andale Mono', 'Lucida Console', monospace + font-size: 12px + +pre + white-space: pre + background-color: #000000 + color: #00FF00 + margin: 5px + margin-bottom: 20px + padding: 5px \ No newline at end of file diff --git a/doc/css/style.sass b/doc/css/style.sass index 69fc573a..4b3965df 100644 --- a/doc/css/style.sass +++ b/doc/css/style.sass @@ -1,131 +1,89 @@ +@import 960/grid +@import 960/text + @import compass/css3 -@import compass/reset +@import compass/layout.scss @import compass/utilities/general @import compass/utilities/lists -$separator: #CCCCCC +@import compass/reset -$size_body_width: 60em -$size_toc_width: 250px +$ninesixty-columns: 24 -$color_a: #569633 -$color_bg: #F9F9F9 -$color_font: #2A2A2A -$color_footer_a: #444444 -$color_footer_border: #CCCCCC -$color_headings: #489848 -$color_headings_border: #CCCCCC -$color_menu_border: #BBBBBB -$color_menu_a: #489848 -$color_note_before: #489848 -$color_note_border: #489848 -$color_pre_bg: #FFFFDD -$color_th_border: #000000 +// Layout + +#container.twocolumn + +grid-container + #header, #menu, #footer, #toc, #content + +grid-unit-base + #header, #menu, #footer + +grid-width(24) + #toc + +grid-width(8) + #content + +grid-width(16) + +// Text + ++text body - background: $color_bg - color: $color_font - line-height: 18px - font-family: Arial, sans-serif - font-size: 100% + font-family: Helvetica, Arial, sans-serif -div.container - display: block - width: $size_body_width - margin: 0 auto +a, a:visited, a:hover, a:active + color: #569633 + text-decoration: none -#header - margin: 1em auto - text-align: center +// Style #menu - width: 100% - margin: 1em 0 1.4em 0 - border-bottom: 1px solid $color_menu_border - text-align: center + margin-bottom: 23px + +border-bottom-radius(10px) + background-color: #959595 + text-align: right + div.logo + float: left + margin-left: 10px + padding-top: 3px ul - +no-bullets display: inline + margin-right: 10px + +no-bullets li display: inline - margin-right: 15px - text-align: center + padding: 0px 3px a - font-size: 20px - font-weight: 700 - color: $color_menu_a - text-decoration: none + font-size: 17px + color: white -#contents.sidebar - float: right - border-left: 1px solid $color_menu_border - width: $size_toc_width - ul - margin-bottom: 0.2em +div.document + border-right: 1px solid #959595 + padding-right: 15px + +#toc + ul ul + list-style: disc + ul ul ul + list-style: circle p.topic-title display: none -div.section - margin-right: $size_toc_width + 20px - -div.section div.section - margin-right: 0 - -div.section ul - margin-left: 15px - +no-bullets - -h1, h2, h3, h4 - color: $color_headings - -h1 - margin-top: 10px - font-size: 26px - -h2 - border-bottom: 5px solid $color_headings_border - margin-bottom: 13px - padding-bottom: 3px - font-size: 20px - font-weight: 700 - -h3 - border-bottom: 1px solid $color_headings_border - margin-bottom: 13px - font-weight: 700 - -a - color: $color_a - text-decoration: none - -p - margin-bottom: 1em - font-size: 1em - -ol - list-style: decimal - margin-left: 2em - margin-bottom: 13px - -ul - list-style: disc - margin-left: 2em - margin-bottom: 13px - pre, tt - font-family: 'andale mono', 'lucida console', monospace + font-family: 'Andale Mono', 'Lucida Console', monospace font-size: 12px - background: $color_pre_bg pre white-space: pre - margin: 3px 3px 2em 3px - padding: 8px 20px + background-color: #000000 + color: #00FF00 + margin: 5px + margin-bottom: 20px + padding: 5px .note - border-top: 1px solid $color_note_border - border-bottom: 1px solid $color_note_border + border-top: 1px solid #569633 + border-bottom: 1px solid #569633 padding: .6em .6em .6em 80px margin-bottom: 2em position: relative @@ -133,9 +91,8 @@ pre content: "!" font-size: 60px font-weight: bold - color: $color_note_before + color: #FF0000 position: absolute - top: 30px left: 30px font-family: helvetica,arial p.admonition-title @@ -148,13 +105,9 @@ pre margin: 0 #footer - border-top: 1px solid $color_footer_border - clear: both - display: block - width: 100% - margin-top: 3em - padding-top: 1em + border-top: 1px solid #959595 + padding: 10px 0px text-align: center - font-size: 0.8em - a - color: $color_footer_a + color: #959595 + p + margin-bottom: 5px \ No newline at end of file diff --git a/doc/htdocs/configure.html b/doc/htdocs/configure.html index f8b72cc2..6df543cd 100644 --- a/doc/htdocs/configure.html +++ b/doc/htdocs/configure.html @@ -7,19 +7,19 @@ -
- + +
diff --git a/doc/htdocs/css/index.css b/doc/htdocs/css/index.css new file mode 100644 index 00000000..078e8381 --- /dev/null +++ b/doc/htdocs/css/index.css @@ -0,0 +1,254 @@ +/* line 14, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, font, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td { + margin: 0; + padding: 0; + border: 0; + outline: 0; + font-weight: inherit; + font-style: inherit; + font-size: 100%; + font-family: inherit; + vertical-align: baseline; +} + +/* line 17, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +body { + line-height: 1; + color: black; + background: white; +} + +/* line 19, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +ol, ul { + list-style: none; +} + +/* line 21, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +table { + border-collapse: separate; + border-spacing: 0; + vertical-align: middle; +} + +/* line 23, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +caption, th, td { + text-align: left; + font-weight: normal; + vertical-align: middle; +} + +/* line 25, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +q, blockquote { + quotes: "" ""; +} +/* line 96, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +q:before, q:after, blockquote:before, blockquote:after { + content: ""; +} + +/* line 27, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +a img { + border: none; +} + +/* line 15, ../../css/index.sass */ +#container.landing { + margin-left: auto; + margin-right: auto; + width: 960px; +} +/* line 17, ../../css/index.sass */ +#container.landing #menu, #container.landing #header, #container.landing div.blurb, #container.landing #tutorial, #container.landing #actions, #container.landing #footer { + display: inline; + float: left; + margin-left: 10px; + margin-right: 10px; +} +/* line 19, ../../css/index.sass */ +#container.landing #menu, #container.landing #header, #container.landing #footer { + width: 940px; +} +/* line 22, ../../css/index.sass */ +#container.landing div.blurb { + width: 300px; +} +/* line 24, ../../css/index.sass */ +#container.landing #tutorial { + width: 620px; +} + +/* line 4, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ +body { + font: 13px/1.5 Helvetica, Arial, 'Liberation Sans', FreeSans, sans-serif; +} + +/* line 6, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ +a:focus { + outline: 1px dotted invert; +} + +/* line 8, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ +hr { + border-color: #cccccc; + border-style: solid; + border-width: 1px 0 0; + clear: both; + height: 0; +} + +/* line 14, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ +h1 { + font-size: 25px; +} + +/* line 16, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ +h2 { + font-size: 23px; +} + +/* line 18, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ +h3 { + font-size: 21px; +} + +/* line 20, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ +h4 { + font-size: 19px; +} + +/* line 22, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ +h5 { + font-size: 17px; +} + +/* line 24, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ +h6 { + font-size: 15px; +} + +/* line 26, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ +ol { + list-style: decimal; +} + +/* line 28, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ +ul { + list-style: square; +} + +/* line 30, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ +li { + margin-left: 30px; +} + +/* line 32, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ +p, +dl, +hr, +h1, +h2, +h3, +h4, +h5, +h6, +ol, +ul, +pre, +table, +address, +fieldset { + margin-bottom: 20px; +} + +/* line 29, ../../css/index.sass */ +a, a:visited, a:hover, a:active { + color: #569633; + text-decoration: none; +} + +/* line 33, ../../css/index.sass */ +#header { + margin: 46px 0px; +} + +/* line 36, ../../css/index.sass */ +#menu { + margin-bottom: 23px; + -moz-border-radius-bottomleft: 10px; + -webkit-border-bottom-left-radius: 10px; + -o-border-bottom-left-radius: 10px; + -ms-border-bottom-left-radius: 10px; + -khtml-border-bottom-left-radius: 10px; + border-bottom-left-radius: 10px; + -moz-border-radius-bottomright: 10px; + -webkit-border-bottom-right-radius: 10px; + -o-border-bottom-right-radius: 10px; + -ms-border-bottom-right-radius: 10px; + -khtml-border-bottom-right-radius: 10px; + border-bottom-right-radius: 10px; + background-color: #959595; + text-align: right; +} +/* line 41, ../../css/index.sass */ +#menu div.logo { + float: left; + margin-left: 10px; + padding-top: 3px; +} +/* line 45, ../../css/index.sass */ +#menu ul { + display: inline; + margin-right: 10px; + list-style: none; +} +/* line 11, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/utilities/lists/_bullets.scss */ +#menu ul li { + list-style-image: none; + list-style-type: none; + margin-left: 0px; +} +/* line 49, ../../css/index.sass */ +#menu ul li { + display: inline; + padding: 0px 3px; +} +/* line 52, ../../css/index.sass */ +#menu ul li a { + font-size: 17px; + color: white; +} + +/* line 56, ../../css/index.sass */ +#footer { + border-top: 1px solid #959595; + padding: 10px 0px; + text-align: center; + color: #959595; +} +/* line 61, ../../css/index.sass */ +#footer p { + margin-bottom: 5px; +} + +/* line 64, ../../css/index.sass */ +pre, tt { + font-family: "Andale Mono", "Lucida Console", monospace; + font-size: 12px; +} + +/* line 68, ../../css/index.sass */ +pre { + white-space: pre; + background-color: black; + color: lime; + margin: 5px; + margin-bottom: 20px; + padding: 5px; +} diff --git a/doc/htdocs/css/style.css b/doc/htdocs/css/style.css index e90ffb2c..6ef65e94 100644 --- a/doc/htdocs/css/style.css +++ b/doc/htdocs/css/style.css @@ -1,4 +1,4 @@ -/* line 14, ../../../../../../../.gem/ruby/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +/* line 14, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, @@ -18,249 +18,288 @@ table, caption, tbody, tfoot, thead, tr, th, td { vertical-align: baseline; } -/* line 17, ../../../../../../../.gem/ruby/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +/* line 17, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ body { line-height: 1; color: black; background: white; } -/* line 19, ../../../../../../../.gem/ruby/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +/* line 19, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ ol, ul { list-style: none; } -/* line 21, ../../../../../../../.gem/ruby/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +/* line 21, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ table { border-collapse: separate; border-spacing: 0; vertical-align: middle; } -/* line 23, ../../../../../../../.gem/ruby/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +/* line 23, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ caption, th, td { text-align: left; font-weight: normal; vertical-align: middle; } -/* line 25, ../../../../../../../.gem/ruby/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +/* line 25, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ q, blockquote { quotes: "" ""; } -/* line 96, ../../../../../../../.gem/ruby/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +/* line 96, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ q:before, q:after, blockquote:before, blockquote:after { content: ""; } -/* line 27, ../../../../../../../.gem/ruby/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +/* line 27, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ a img { border: none; } -/* line 25, ../../css/style.sass */ +/* line 15, ../../css/style.sass */ +#container.twocolumn { + margin-left: auto; + margin-right: auto; + width: 960px; +} +/* line 17, ../../css/style.sass */ +#container.twocolumn #header, #container.twocolumn #menu, #container.twocolumn #footer, #container.twocolumn #toc, #container.twocolumn #content { + display: inline; + float: left; + margin-left: 10px; + margin-right: 10px; +} +/* line 19, ../../css/style.sass */ +#container.twocolumn #header, #container.twocolumn #menu, #container.twocolumn #footer { + width: 940px; +} +/* line 21, ../../css/style.sass */ +#container.twocolumn #toc { + width: 300px; +} +/* line 23, ../../css/style.sass */ +#container.twocolumn #content { + width: 620px; +} + +/* line 4, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ body { - background: #f9f9f9; - color: #2a2a2a; - line-height: 18px; - font-family: Arial, sans-serif; - font-size: 100%; + font: 13px/1.5 Helvetica, Arial, 'Liberation Sans', FreeSans, sans-serif; } -/* line 32, ../../css/style.sass */ -div.container { - display: block; - width: 60em; - margin: 0 auto; +/* line 6, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ +a:focus { + outline: 1px dotted invert; } -/* line 37, ../../css/style.sass */ -#header { - margin: 1em auto; - text-align: center; +/* line 8, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ +hr { + border-color: #cccccc; + border-style: solid; + border-width: 1px 0 0; + clear: both; + height: 0; } -/* line 41, ../../css/style.sass */ -#menu { - width: 100%; - margin: 1em 0 1.4em 0; - border-bottom: 1px solid #bbbbbb; - text-align: center; -} -/* line 46, ../../css/style.sass */ -#menu ul { - list-style: none; - display: inline; -} -/* line 11, ../../../../../../../.gem/ruby/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/utilities/lists/_bullets.scss */ -#menu ul li { - list-style-image: none; - list-style-type: none; - margin-left: 0px; -} -/* line 49, ../../css/style.sass */ -#menu ul li { - display: inline; - margin-right: 15px; - text-align: center; -} -/* line 53, ../../css/style.sass */ -#menu ul li a { - font-size: 20px; - font-weight: 700; - color: #489848; - text-decoration: none; -} - -/* line 59, ../../css/style.sass */ -#contents.sidebar { - float: right; - border-left: 1px solid #bbbbbb; - width: 250px; -} -/* line 63, ../../css/style.sass */ -#contents.sidebar ul { - margin-bottom: 0.2em; -} - -/* line 66, ../../css/style.sass */ -p.topic-title { - display: none; -} - -/* line 69, ../../css/style.sass */ -div.section { - margin-right: 270px; -} - -/* line 72, ../../css/style.sass */ -div.section div.section { - margin-right: 0; -} - -/* line 75, ../../css/style.sass */ -div.section ul { - margin-left: 15px; - list-style: none; -} -/* line 11, ../../../../../../../.gem/ruby/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/utilities/lists/_bullets.scss */ -div.section ul li { - list-style-image: none; - list-style-type: none; - margin-left: 0px; -} - -/* line 79, ../../css/style.sass */ -h1, h2, h3, h4 { - color: #489848; -} - -/* line 82, ../../css/style.sass */ +/* line 14, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ h1 { - margin-top: 10px; - font-size: 26px; + font-size: 25px; } -/* line 86, ../../css/style.sass */ +/* line 16, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ h2 { - border-bottom: 5px solid #cccccc; - margin-bottom: 13px; - padding-bottom: 3px; - font-size: 20px; - font-weight: 700; + font-size: 23px; } -/* line 93, ../../css/style.sass */ +/* line 18, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ h3 { - border-bottom: 1px solid #cccccc; - margin-bottom: 13px; - font-weight: 700; + font-size: 21px; } -/* line 98, ../../css/style.sass */ -a { +/* line 20, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ +h4 { + font-size: 19px; +} + +/* line 22, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ +h5 { + font-size: 17px; +} + +/* line 24, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ +h6 { + font-size: 15px; +} + +/* line 26, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ +ol { + list-style: decimal; +} + +/* line 28, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ +ul { + list-style: square; +} + +/* line 30, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ +li { + margin-left: 30px; +} + +/* line 32, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-960-plugin-0.9.13/stylesheets/960/_text.sass */ +p, +dl, +hr, +h1, +h2, +h3, +h4, +h5, +h6, +ol, +ul, +pre, +table, +address, +fieldset { + margin-bottom: 20px; +} + +/* line 30, ../../css/style.sass */ +body { + font-family: Helvetica, Arial, sans-serif; +} + +/* line 33, ../../css/style.sass */ +a, a:visited, a:hover, a:active { color: #569633; text-decoration: none; } -/* line 102, ../../css/style.sass */ -p { - margin-bottom: 1em; - font-size: 1em; +/* line 39, ../../css/style.sass */ +#menu { + margin-bottom: 23px; + -moz-border-radius-bottomleft: 10px; + -webkit-border-bottom-left-radius: 10px; + -o-border-bottom-left-radius: 10px; + -ms-border-bottom-left-radius: 10px; + -khtml-border-bottom-left-radius: 10px; + border-bottom-left-radius: 10px; + -moz-border-radius-bottomright: 10px; + -webkit-border-bottom-right-radius: 10px; + -o-border-bottom-right-radius: 10px; + -ms-border-bottom-right-radius: 10px; + -khtml-border-bottom-right-radius: 10px; + border-bottom-right-radius: 10px; + background-color: #959595; + text-align: right; +} +/* line 44, ../../css/style.sass */ +#menu div.logo { + float: left; + margin-left: 10px; + padding-top: 3px; +} +/* line 48, ../../css/style.sass */ +#menu ul { + display: inline; + margin-right: 10px; + list-style: none; +} +/* line 11, ../../../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.10.1/frameworks/compass/stylesheets/compass/utilities/lists/_bullets.scss */ +#menu ul li { + list-style-image: none; + list-style-type: none; + margin-left: 0px; +} +/* line 52, ../../css/style.sass */ +#menu ul li { + display: inline; + padding: 0px 3px; +} +/* line 55, ../../css/style.sass */ +#menu ul li a { + font-size: 17px; + color: white; } -/* line 106, ../../css/style.sass */ -ol { - list-style: decimal; - margin-left: 2em; - margin-bottom: 13px; +/* line 59, ../../css/style.sass */ +div.document { + border-right: 1px solid #959595; + padding-right: 15px; } -/* line 111, ../../css/style.sass */ -ul { +/* line 64, ../../css/style.sass */ +#toc ul ul { list-style: disc; - margin-left: 2em; - margin-bottom: 13px; +} +/* line 66, ../../css/style.sass */ +#toc ul ul ul { + list-style: circle; } -/* line 116, ../../css/style.sass */ +/* line 69, ../../css/style.sass */ +p.topic-title { + display: none; +} + +/* line 72, ../../css/style.sass */ pre, tt { - font-family: "andale mono", "lucida console", monospace; + font-family: "Andale Mono", "Lucida Console", monospace; font-size: 12px; - background: #ffffdd; } -/* line 121, ../../css/style.sass */ +/* line 76, ../../css/style.sass */ pre { white-space: pre; - margin: 3px 3px 2em 3px; - padding: 8px 20px; + background-color: black; + color: lime; + margin: 5px; + margin-bottom: 20px; + padding: 5px; } -/* line 126, ../../css/style.sass */ +/* line 84, ../../css/style.sass */ .note { - border-top: 1px solid #489848; - border-bottom: 1px solid #489848; + border-top: 1px solid #569633; + border-bottom: 1px solid #569633; padding: 0.6em 0.6em 0.6em 80px; margin-bottom: 2em; position: relative; } -/* line 132, ../../css/style.sass */ +/* line 90, ../../css/style.sass */ .note p.admonition-title:before { content: "!"; font-size: 60px; font-weight: bold; - color: #489848; + color: red; position: absolute; - top: 30px; left: 30px; font-family: helvetica, arial; } -/* line 141, ../../css/style.sass */ +/* line 98, ../../css/style.sass */ .note p.admonition-title { font-weight: 700; margin: 0; margin-bottom: 4px; padding: 0; } -/* line 146, ../../css/style.sass */ +/* line 103, ../../css/style.sass */ .note p.last { padding: 0; margin: 0; } -/* line 150, ../../css/style.sass */ +/* line 107, ../../css/style.sass */ #footer { - border-top: 1px solid #cccccc; - clear: both; - display: block; - width: 100%; - margin-top: 3em; - padding-top: 1em; + border-top: 1px solid #959595; + padding: 10px 0px; text-align: center; - font-size: 0.8em; + color: #959595; } -/* line 159, ../../css/style.sass */ -#footer a { - color: #444444; +/* line 112, ../../css/style.sass */ +#footer p { + margin-bottom: 5px; } diff --git a/doc/htdocs/deploy.html b/doc/htdocs/deploy.html index 13dad92b..55e73d77 100644 --- a/doc/htdocs/deploy.html +++ b/doc/htdocs/deploy.html @@ -7,19 +7,19 @@ -
- +
-

Nginx Configuration

Although there are many HTTP proxies available, we strongly advise that you @@ -173,7 +161,7 @@ exec $GUNICORN -C $ROOT/gunicorn.conf.py --pidfile=$PID $APP simple configuration is:

 [program:gunicorn]
-command=/usr/local/bin/gunicorn main:application -c /path/to/project/gunicorn.conf.py
+command=/path/to/gunicorn main:application -c /path/to/gunicorn.conf.py
 directory=/path/to/project
 user=nobody
 autostart=true
@@ -183,10 +171,23 @@ redirect_stderr=True
 
- +
+
diff --git a/doc/htdocs/design.html b/doc/htdocs/design.html index 36b0e543..781ce81e 100644 --- a/doc/htdocs/design.html +++ b/doc/htdocs/design.html @@ -7,19 +7,19 @@ -
- +
-

Server Model

Gunicorn is based on the pre-fork worker model. This means that there is a @@ -120,10 +106,25 @@ worker processes will start thrashing system resources decreasing the throughput of the entire system.

- +
+
diff --git a/doc/htdocs/faq.html b/doc/htdocs/faq.html index 3903f077..5a70aa05 100644 --- a/doc/htdocs/faq.html +++ b/doc/htdocs/faq.html @@ -7,19 +7,19 @@ -
- +
-
-

Questions

+
+

WSGI Bits

+
+

How do I set SCRIPT_NAME?

+

By default SCRIPT_NAME is an empy string. The value could be set by +setting SCRIPT_NAME in the environment or as an HTTP header.

+
+
+
+

Server Stuff

+
+

How do I reload my application in Gunicorn?

+

You can gracefully reload by sending HUP signal to gunicorn:

+
+$ kill -HUP masterpid
+
+
+
+

How might I test a proxy configuration?

+

The Slowloris script is a great way to test that your proxy is correctly +buffering responses for the synchronous workers.

+
+
+

How can I name processes?

+

If you install the Python package setproctitle Gunicorn will set the process +names to something a bit more meaningful. This will affect the output you see +in tools like ps and top. This helps for distinguishing the master +process as well as between masters when running more than one app on a single +machine. See the proc_name setting for more information.

+
+
+
+

Worker Processes

+
+

How do I know which type of worker to use?

+

Read the design page for help on the various worker types.

+
+
+

What types of workers are there?

+

Check out the configuration docs for worker_class

+
+ +
+

How can I change the number of workers dynamically?

+
+

To increase the worker count by one:

+
+$ kill -TTIN $masterpid
+
+

To decrease the worker count by one:

+
+$ kill -TTOU $masterpid
+
+
+
+
+
+

Kernel Parameters

+

When dealing with large numbers of concurrent connections there are a handful of +kernel parameters that you might need to adjust. Generally these should only +affect sites with a very large concurrent load. These parameters are not +specific to Gunicorn, they would apply to any sort of network server you may be +running.

+

These commands are for Linux. Your particular OS may have slightly different +parameters.

+
+

How can I increase the maximum number of file descriptors?

+

One of the first settings that usually needs to be bumped is the maximum number +of open file descriptors for a given process. For the confused out there, +remember that Unices treat sockets as files.

+
+$ sudo ulimit -n 2048
+
+
+
+

How can I increase the maximum socket backlog?

+

Listening sockets have an associated queue of incoming connections that are +waiting to be accepted. If you happen to have a stampede of clients that fill up +this queue new connections will eventually start getting dropped.

+
+$ sudo sysctl -w net.core.somaxconn="2048"
+
+
+
+
+
+
+
+

Contents

-
-

WSGI Bits

-
-

How do I set SCRIPT_NAME?

-

By default SCRIPT_NAME is an empy string. The value could be set by -setting SCRIPT_NAME in the environment or as an HTTP header.

-
-
-
-

Server Stuff

-
-

How do I reload my application in Gunicorn?

-

You can gracefully reload by sending HUP signal to gunicorn:

-
-$ kill -HUP masterpid
-
-
-
-

How might I test a proxy configuration?

-

The Slowloris script is a great way to test that your proxy is correctly -buffering responses for the synchronous workers.

-
-
-

How can I name processes?

-

If you install the Python package setproctitle Gunicorn will set the process -names to something a bit more meaningful. This will affect the output you see -in tools like ps and top. This helps for distinguishing the master -process as well as between masters when running more than one app on a single -machine. See the proc_name setting for more information.

-
-
-
-

Worker Processes

-
-

How do I know which type of worker to use?

-

Read the design page for help on the various worker types.

-
-
-

What types of workers are there?

-

Check out the configuration docs for worker_class

-
- -
-

How can I change the number of workers dynamically?

-
-

To increase the worker count by one:

-
-$ kill -TTIN $masterpid
-
-

To decrease the worker count by one:

-
-$ kill -TTOU $masterpid
-
-
-
-
-
-

Kernel Parameters

-

When dealing with large numbers of concurrent connections there are a handful of -kernel parameters that you might need to adjust. Generally these should only -affect sites with a very large concurrent load. These parameters are not -specific to Gunicorn, they would apply to any sort of network server you may be -running.

-

These commands are for Linux. Your particular OS may have slightly different -parameters.

-
-

How can I increase the maximum number of file descriptors?

-

One of the first settings that usually needs to be bumped is the maximum number -of open file descriptors for a given process. For the confused out there, -remember that Unices treat sockets as files.

-
-$ sudo ulimit -n 2048
-
-
-
-

How can I increase the maximum socket backlog?

-

Listening sockets have an associated queue of incoming connections that are -waiting to be accepted. If you happen to have a stampede of clients that fill up -this queue new connections will eventually start getting dropped.

-
-$ sudo sysctl -w net.core.somaxconn="2048"
-
-
-
-
-
diff --git a/doc/htdocs/images/gunicorn.png b/doc/htdocs/images/gunicorn.png new file mode 100644 index 0000000000000000000000000000000000000000..940db5474875e07edfc0d8a410ad9da612f68670 GIT binary patch literal 1581 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 Pi@?R->@12=xcmPHQD$yc literal 0 HcmV?d00001 diff --git a/doc/htdocs/index.html b/doc/htdocs/index.html index bb93598b..5b890248 100644 --- a/doc/htdocs/index.html +++ b/doc/htdocs/index.html @@ -4,74 +4,92 @@ Green Unicorn - Welcome - + -
- +
-
-
-
-

Green Unicorn

-

Gunicorn 'Green Unicorn' is a WSGI HTTP Server for UNIX. It's a pre-fork -worker model ported from Ruby's Unicorn project. The Gunicorn server is -broadly compatible with various web frameworks, simply implemented, light -on server resource usage, and fairly speedy.

-

Feel free to join us in #gunicorn on freenode.

-

Gunicorn is released under the MIT License. See the LICENSE for more details.

-
-
-

Features

-
    -
  • Designed for Unix.
  • -
  • Compatible with Python 2.x (>= 2.5)
  • -
  • Easy integration with Django and Paster applications -(Pylons, TurboGears 2, ...)
  • -
  • Process management: Gunicorn reaps and restarts workers that die.
  • -
  • Load balancing via pre-fork and a shared socket
  • -
  • Graceful worker process restarts
  • -
  • Upgrade "àla nginx" without losing connections
  • -
  • Simple and easy Python configuration
  • -
  • Decode chunked transfers on-the-fly, allowing upload progress notifications -or stream-based protocols over HTTP
  • -
  • Support for Eventlet and Gevent .
  • -
  • Post- and pre-fork hooks
  • -
-
-
-

Applications

- -
-
- + +
+

Quick Start

+
+$ sudo easy_install virtualenv
+$ mkdir ~/environments/
+$ virtualenv ~/environments/tutorial/
+$ cd ~/environments/tutorial/
+$ ls
+bin  include  lib
+$ source bin/activate
+(tutorial) $ clear
+(tutorial) $ ./bin/easy_install gunicorn
+(tutorial) $ mkdir myapp
+(tutorial) $ cd myapp/
+(tutorial) $ vi myapp.py
+(tutorial) $ cat myapp.py 
+
+def app(environ, start_response):
+    data = "Hello, World!\n"
+    start_response("200 OK", [
+        ("Content-Type", "text/plain"),
+        ("Content-Length", str(len(data)))
+    ])
+    return iter([data])
+
+(tutorial) $ ../bin/gunicorn -w 4 myapp:app
+2010-06-05 23:27:07 [16800] [INFO] Arbiter booted
+2010-06-05 23:27:07 [16800] [INFO] Listening at: http://127.0.0.1:8000
+2010-06-05 23:27:07 [16801] [INFO] Worker spawned (pid: 16801)
+2010-06-05 23:27:07 [16802] [INFO] Worker spawned (pid: 16802)
+2010-06-05 23:27:07 [16803] [INFO] Worker spawned (pid: 16803)
+2010-06-05 23:27:07 [16804] [INFO] Worker spawned (pid: 16804)
+
+
+
+

About

+

+ Gunicorn 'Green Unicorn' is a WSGI HTTP Server for UNIX. It's a + pre-fork worker model ported from Ruby's Unicorn project. The + Gunicorn server is broadly compatible with various web frameworks, + simply implemented, light on server resources, and fairly speedy. +

+
+
+

Features

+
    +
  • Natively supports WSGI, Django, and Paster
  • +
  • Automatic worker process management
  • +
  • Simple Python configuration
  • +
  • Multiple worker configurations
  • +
  • Various server hooks for extensibility
  • +
  • Compatible with Python 2.x >= 2.5
  • +
+
+
+

Version 0.9.1 - 2010-05-26

+
    +
  • Support https via X-Forwarded-Protocol or X-Forwarded-Ssl headers
  • +
  • Remove -d command line to avoid confusion with -D
  • +
  • Fixed a minor configuration bug
  • +
  • Fixed umask for Unix sockets
  • +
+
- \ No newline at end of file + diff --git a/doc/htdocs/install.html b/doc/htdocs/install.html index 968d331f..4c93e962 100644 --- a/doc/htdocs/install.html +++ b/doc/htdocs/install.html @@ -7,19 +7,19 @@ -
- +
-

Requirements

    @@ -138,10 +124,25 @@ deb-src http://ppa.launchpad.net/bchesneau/gunicorn/ubuntu karmic main
- +
+
diff --git a/doc/htdocs/news.html b/doc/htdocs/news.html index 45fb2338..8f57c9c4 100644 --- a/doc/htdocs/news.html +++ b/doc/htdocs/news.html @@ -7,19 +7,19 @@ -
- +
diff --git a/doc/htdocs/run.html b/doc/htdocs/run.html index f5046b8d..885df716 100644 --- a/doc/htdocs/run.html +++ b/doc/htdocs/run.html @@ -7,19 +7,19 @@ -
- +
-

Commands

After installing Gunicorn you will have access to three command line scripts @@ -154,10 +138,27 @@ $ paster serve development.ini workers=2

- +
+
diff --git a/doc/site/configure.rst b/doc/site/configure.rst index 9eccd786..adb13bb9 100644 --- a/doc/site/configure.rst +++ b/doc/site/configure.rst @@ -2,10 +2,13 @@ template: doc.html title: Configure insert_settings: true +_TOC_TOP_ + .. contents:: - :class: sidebar :backlinks: top +_TOC_BOT_ + Overview -------- diff --git a/doc/site/deploy.rst b/doc/site/deploy.rst index 888b25e7..e46338be 100644 --- a/doc/site/deploy.rst +++ b/doc/site/deploy.rst @@ -1,10 +1,13 @@ template: doc.html title: Deploy +_TOC_TOP_ + .. contents:: - :class: sidebar :backlinks: top +_TOC_BOT_ + Nginx Configuration ------------------- @@ -145,7 +148,7 @@ Another useful tool to monitor and control Gunicorn is Supervisor_. A `simple configuration`_ is:: [program:gunicorn] - command=/usr/local/bin/gunicorn main:application -c /path/to/project/gunicorn.conf.py + command=/path/to/gunicorn main:application -c /path/to/gunicorn.conf.py directory=/path/to/project user=nobody autostart=true diff --git a/doc/site/design.rst b/doc/site/design.rst index de157147..777c97a2 100644 --- a/doc/site/design.rst +++ b/doc/site/design.rst @@ -1,10 +1,13 @@ template: doc.html title: Design +_TOC_TOP_ + .. contents:: - :class: sidebar :backlinks: top +_TOC_BOT_ + Server Model ============ diff --git a/doc/site/faq.rst b/doc/site/faq.rst index b9c71576..08fd8366 100644 --- a/doc/site/faq.rst +++ b/doc/site/faq.rst @@ -1,9 +1,13 @@ template: doc.html title: FAQ -.. contents:: Questions +_TOC_TOP_ + +.. contents:: :backlinks: top +_TOC_BOT_ + WSGI Bits ========= diff --git a/doc/site/index.rst b/doc/site/index.rst deleted file mode 100644 index a551c284..00000000 --- a/doc/site/index.rst +++ /dev/null @@ -1,57 +0,0 @@ -template: index.html -title: Welcome - -Green Unicorn -------------- - -Gunicorn 'Green Unicorn' is a WSGI_ HTTP Server for UNIX. It's a pre-fork -worker model ported from Ruby's Unicorn_ project. The Gunicorn server is -broadly compatible with various web frameworks, simply implemented, light -on server resource usage, and fairly speedy. - -Feel free to join us in `#gunicorn`_ on freenode_. - -Gunicorn is released under the MIT License. See the LICENSE_ for more details. - -Features --------- - -- Designed for Unix. -- Compatible with Python 2.x (>= 2.5) -- Easy integration with Django_ and Paster_ applications - (`Pylons`_, `TurboGears 2`_, ...) -- Process management: Gunicorn_ reaps and restarts workers that die. -- Load balancing via pre-fork and a shared socket -- Graceful worker process restarts -- Upgrade "àla nginx" without losing connections -- Simple and easy Python configuration -- Decode chunked transfers on-the-fly, allowing upload progress notifications - or stream-based protocols over HTTP -- Support for `Eventlet`_ and `Gevent`_ . -- Post- and pre-fork hooks - -Applications ------------- - -* Any WSGI_, Django_ and Paster_ compatible applications - (`Pylons`_, `TurboGears 2`_, ...) -* Websockets (see the example_ or the screencast_) -* Reverse proxy implementation (with `Restkit WSGI proxy`_) -* Long Polling -* Comet - -.. _WSGI: http://www.python.org/dev/peps/pep-0333/ -.. _Unicorn: http://unicorn.bogomips.org/ -.. _`#gunicorn`: http://webchat.freenode.net/?channels=gunicorn -.. _freenode: http://freenode.net -.. _LICENSE: http://github.com/benoitc/gunicorn/blob/master/LICENSE -.. _Gunicorn: http://gunicorn.org -.. _Django: http://djangoproject.com -.. _Paster: http://pythonpaste.org/ -.. _Eventlet: http://eventlet.net -.. _Gevent: http://gevent.org -.. _Pylons: http://pylonshq.com/ -.. _Turbogears 2: http://turbogears.org/2.0/ -.. _example: http://github.com/benoitc/gunicorn/blob/master/examples/websocket.py -.. _`Restkit WSGI proxy`: http://benoitc.github.com/restkit/wsgi_proxy.html -.. _screencast: http://vimeo.com/10461162 diff --git a/doc/site/install.rst b/doc/site/install.rst index c14650a4..e71639ef 100644 --- a/doc/site/install.rst +++ b/doc/site/install.rst @@ -1,10 +1,13 @@ template: doc.html title: Install +_TOC_TOP_ + .. contents:: - :class: sidebar :backlinks: top +_TOC_BOT_ + Requirements ------------ diff --git a/doc/site/news.rst b/doc/site/news.rst index ecbdb937..dfdb2708 100644 --- a/doc/site/news.rst +++ b/doc/site/news.rst @@ -1,6 +1,13 @@ template: doc.html title: News +_TOC_TOP_ + +.. contents:: + :backlinks: top + +_TOC_BOT_ + 0.9.1 / 2010-05-26 ------------------ diff --git a/doc/site/run.rst b/doc/site/run.rst index 248f5209..cec9fb3a 100644 --- a/doc/site/run.rst +++ b/doc/site/run.rst @@ -1,10 +1,13 @@ template: doc.html title: Run +_TOC_TOP_ + .. contents:: - :class: sidebar :backlinks: top +_TOC_BOT_ + Commands -------- diff --git a/doc/sitemap_gen.py b/doc/sitemap_gen.py index cbcfd6f5..f4f28e10 100755 --- a/doc/sitemap_gen.py +++ b/doc/sitemap_gen.py @@ -62,7 +62,7 @@ if sys.hexversion < 0x02020000: import fnmatch import glob import gzip -import md5 +import hashlib import os import re import stat @@ -388,7 +388,7 @@ class Output: """ Output and count a warning. Suppress duplicate warnings. """ if text: text = encoder.NarrowText(text, None) - hash = md5.new(text).digest() + hash = hashlib.md5(text).hexdigest() if not self._warns_shown.has_key(hash): self._warns_shown[hash] = 1 print '[WARNING] ' + text @@ -401,7 +401,7 @@ class Output: """ Output and count an error. Suppress duplicate errors. """ if text: text = encoder.NarrowText(text, None) - hash = md5.new(text).digest() + hash = hashlib.md5(text).hexdigest() if not self._errors_shown.has_key(hash): self._errors_shown[hash] = 1 print '[ERROR] ' + text @@ -604,8 +604,8 @@ class URL(object): if not self.loc: return None if self.loc.endswith('/'): - return md5.new(self.loc[:-1]).digest() - return md5.new(self.loc).digest() + return hashlib.md5(self.loc[:-1]).hexdigest() + return hashlib.md5(self.loc).hexdigest() #end def MakeHash def Log(self, prefix='URL', level=3): diff --git a/doc/templates/base.html b/doc/templates/base.html index 7182a8a0..966ada46 100644 --- a/doc/templates/base.html +++ b/doc/templates/base.html @@ -7,19 +7,19 @@ -
- +
diff --git a/doc/templates/doc.html b/doc/templates/doc.html index 67752fe0..a55ef97f 100644 --- a/doc/templates/doc.html +++ b/doc/templates/doc.html @@ -1,4 +1,6 @@ {% extends "base.html" %} {% block title %}{{ title }}{% endblock %} +{% if toc %} {% block toc %}{{ toc }}{% endblock %} +{% endif %} {% block body %}{{ body }}{% endblock %} \ No newline at end of file diff --git a/doc/templates/index.html b/doc/templates/index.html index 8e9f3682..26a43ebb 100644 --- a/doc/templates/index.html +++ b/doc/templates/index.html @@ -1,2 +1,23 @@ -{% extends "base.html" %} -{% block body %}{{ body }}{% endblock %} \ No newline at end of file + + + + + Green Unicorn - {% block title %}Welcome{% endblock %} + + + + +
+ +
+ {% block body %}{% endblock %} +
+ +
+ + \ No newline at end of file