diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2014-12-16 12:16:46 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2014-12-16 12:16:46 -0500 |
commit | 3e55a0bf107143031fd183aef1028aef842c7d3f (patch) | |
tree | 75fb2f46b86df2b6ed51097cd5e58aad07dd3a96 | |
parent | 91eb1b41e3a629b8f666f80142502ae88cba73f2 (diff) | |
download | sqlalchemy-3e55a0bf107143031fd183aef1028aef842c7d3f.tar.gz |
- add scss support
- start modularizing things
-rw-r--r-- | doc/build/builder/autodoc_mods.py | 50 | ||||
-rw-r--r-- | doc/build/builder/dialect_info.py | 15 | ||||
-rw-r--r-- | doc/build/builder/mako.py | 25 | ||||
-rw-r--r-- | doc/build/builder/scss.py | 46 | ||||
-rw-r--r-- | doc/build/builder/toc.py | 56 | ||||
-rw-r--r-- | doc/build/conf.py | 18 | ||||
-rw-r--r-- | doc/build/static/docs.scss (renamed from doc/build/static/docs.css) | 102 | ||||
-rw-r--r-- | doc/build/templates/layout.mako | 7 |
8 files changed, 204 insertions, 115 deletions
diff --git a/doc/build/builder/autodoc_mods.py b/doc/build/builder/autodoc_mods.py index 5a6e991bd..78c94b615 100644 --- a/doc/build/builder/autodoc_mods.py +++ b/doc/build/builder/autodoc_mods.py @@ -10,27 +10,11 @@ def autodoc_skip_member(app, what, name, obj, skip, options): return skip -_convert_modname = { - "sqlalchemy.sql.sqltypes": "sqlalchemy.types", - "sqlalchemy.sql.type_api": "sqlalchemy.types", - "sqlalchemy.sql.schema": "sqlalchemy.schema", - "sqlalchemy.sql.elements": "sqlalchemy.sql.expression", - "sqlalchemy.sql.selectable": "sqlalchemy.sql.expression", - "sqlalchemy.sql.dml": "sqlalchemy.sql.expression", - "sqlalchemy.sql.ddl": "sqlalchemy.schema", - "sqlalchemy.sql.base": "sqlalchemy.sql.expression" -} - -_convert_modname_w_class = { - ("sqlalchemy.engine.interfaces", "Connectable"): "sqlalchemy.engine", - ("sqlalchemy.sql.base", "DialectKWArgs"): "sqlalchemy.sql.base", -} - -def _adjust_rendered_mod_name(modname, objname): - if (modname, objname) in _convert_modname_w_class: - return _convert_modname_w_class[(modname, objname)] - elif modname in _convert_modname: - return _convert_modname[modname] +def _adjust_rendered_mod_name(config, modname, objname): + if (modname, objname) in config.autodocmods_convert_modname_w_class: + return config.autodocmods_convert_modname_w_class[(modname, objname)] + elif modname in config.autodocmods_convert_modname: + return config.autodocmods_convert_modname[modname] else: return modname @@ -49,7 +33,8 @@ def autodoc_process_docstring(app, what, name, obj, options, lines): for base in obj.__bases__: if base is not object: bases.append(":class:`%s.%s`" % ( - _adjust_rendered_mod_name(base.__module__, base.__name__), + _adjust_rendered_mod_name( + app.env.config, base.__module__, base.__name__), base.__name__)) if bases: @@ -70,19 +55,28 @@ def autodoc_process_docstring(app, what, name, obj, options, lines): if attrname in supercls.__dict__: break if supercls is not cls: - _inherited_names.add("%s.%s" % (supercls.__module__, supercls.__name__)) - _inherited_names.add("%s.%s.%s" % (supercls.__module__, supercls.__name__, attrname)) + _inherited_names.add( + "%s.%s" % (supercls.__module__, supercls.__name__)) + _inherited_names.add( + "%s.%s.%s" % + (supercls.__module__, supercls.__name__, attrname)) lines[:0] = [ ".. container:: inherited_member", "", - " *inherited from the* :%s:`~%s.%s.%s` *%s of* :class:`~%s.%s`" % ( + " *inherited from the* " + ":%s:`~%s.%s.%s` *%s of* :class:`~%s.%s`" % ( "attr" if what == "attribute" else "meth", - _adjust_rendered_mod_name(supercls.__module__, supercls.__name__), + _adjust_rendered_mod_name( + app.env.config, + supercls.__module__, + supercls.__name__), supercls.__name__, attrname, what, - _adjust_rendered_mod_name(supercls.__module__, supercls.__name__), + _adjust_rendered_mod_name(app.env.config, + supercls.__module__, + supercls.__name__), supercls.__name__ ), "" @@ -98,5 +92,7 @@ def missing_reference(app, env, node, contnode): def setup(app): app.connect('autodoc-skip-member', autodoc_skip_member) app.connect('autodoc-process-docstring', autodoc_process_docstring) + app.add_config_value("autodocmods_convert_modname", {}, 'env') + app.add_config_value("autodocmods_convert_modname_w_class", {}, 'env') app.connect('missing-reference', missing_reference) diff --git a/doc/build/builder/dialect_info.py b/doc/build/builder/dialect_info.py index 48626393d..eec4cb6dc 100644 --- a/doc/build/builder/dialect_info.py +++ b/doc/build/builder/dialect_info.py @@ -30,7 +30,8 @@ class DialectDirective(Directive): try: dialect_directive = self._dialects[dialect_name] except KeyError: - raise Exception("No .. dialect:: %s directive has been established" + raise Exception( + "No .. dialect:: %s directive has been established" % dialect_name) output = [] @@ -64,7 +65,8 @@ class DialectDirective(Directive): ids=["dialect-%s-%s-url" % (dialect_name, dbapi_name)] ) if "url" in content: - text = "Documentation and download information (if applicable) "\ + text = "Documentation and download information "\ + "(if applicable) "\ "for %s is available at:\n" % content["name"] uri = content['url'] sec.append( @@ -82,7 +84,8 @@ class DialectDirective(Directive): nodes.paragraph('', '', nodes.Text(text, text), nodes.reference('', '', - nodes.Text(content['driverurl'], content['driverurl']), + nodes.Text(content['driverurl'], + content['driverurl']), refuri=content['driverurl'] ) ) @@ -113,7 +116,8 @@ class DialectDirective(Directive): self.bullets = nodes.bullet_list() text = "The following dialect/DBAPI options are available. "\ - "Please refer to individual DBAPI sections for connect information." + "Please refer to individual DBAPI sections "\ + "for connect information." sec = nodes.section('', nodes.paragraph('', '', nodes.Text( @@ -135,7 +139,8 @@ class DialectDirective(Directive): env = self.state.document.settings.env dialect_directive = self._dialects[dialect_name] try: - relative_uri = env.app.builder.get_relative_uri(dialect_directive.docname, self.docname) + relative_uri = env.app.builder.get_relative_uri( + dialect_directive.docname, self.docname) except: relative_uri = "" list_node = nodes.list_item('', diff --git a/doc/build/builder/mako.py b/doc/build/builder/mako.py index 8d2c1ac3e..770fcae55 100644 --- a/doc/build/builder/mako.py +++ b/doc/build/builder/mako.py @@ -25,16 +25,23 @@ class MakoBridge(TOCMixin, TemplateBridge): ] ) - if rtd: - # RTD layout, imported from sqlalchemy.org + if rtd and builder.config['site_base']: import urllib2 - template = urllib2.urlopen(builder.config['site_base'] + "/docs_adapter.mako").read() - self.lookup.put_string("docs_adapter.mako", template) + if builder_config['site_adapter_file']: + # remote site layout / startup files + template_name = builder_config['site_adapter_template'] - setup_ctx = urllib2.urlopen(builder.config['site_base'] + "/docs_adapter.py").read() - lcls = {} - exec(setup_ctx, lcls) - self.setup_ctx = lcls['setup_context'] + template = urllib2.urlopen( + builder.config['site_base'] + "/" + template_name).read() + self.lookup.put_string(template_name, template) + + py_name = builder_config['site_adapter_py'] + if py_name: + setup_ctx = urllib2.urlopen( + builder.config['site_base'] + "/", py_name).read() + lcls = {} + exec(setup_ctx, lcls) + self.setup_ctx = lcls['setup_context'] def setup_ctx(self, context): pass @@ -64,5 +71,7 @@ def setup(app): app.config['template_bridge'] = "builder.mako.MakoBridge" app.add_config_value('release_date', "", 'env') app.add_config_value('site_base', "", 'env') + app.add_config_value('site_adapter_template', "", 'env') + app.add_config_value('site_adapter_py', "", 'env') app.add_config_value('build_number', "", 'env') diff --git a/doc/build/builder/scss.py b/doc/build/builder/scss.py new file mode 100644 index 000000000..ea7247096 --- /dev/null +++ b/doc/build/builder/scss.py @@ -0,0 +1,46 @@ +from __future__ import absolute_import + +import os +from scss import Scss + +# these docs aren't super accurate +# http://pyscss.readthedocs.org/en/latest/ + +def add_stylesheet(app): + to_gen = [] + for static_path in app.env.config.html_static_path: + path = os.path.join(app.env.srcdir, static_path) + for fname in os.listdir(path): + name, ext = os.path.splitext(fname) + if ext != ".scss": + continue + to_gen.append((path, name)) + + # sphinx doesn't really have a "temp" area that will persist + # down into build-finished (env.temp_data gets emptied). + # So make our own! + app._builder_scss = to_gen + + for path, name in to_gen: + app.add_stylesheet('%s.css' % name) + +def generate_stylesheet(app, exception): + to_gen = app._builder_scss + + compiler = Scss(scss_opts={"style": "expanded"}) + for static_path, name in to_gen: + + css = compiler.compile( + open(os.path.join(static_path, "%s.scss" % name)).read()) + + dest = os.path.join(app.builder.outdir, '_static', '%s.css' % name) + #copyfile(os.path.join(source, "%s.css" % name), dest) + + with open(dest, "w") as out: + out.write(css) + + +def setup(app): + app.connect('builder-inited', add_stylesheet) + app.connect('build-finished', generate_stylesheet) + diff --git a/doc/build/builder/toc.py b/doc/build/builder/toc.py index 6ac75209a..89b6dec51 100644 --- a/doc/build/builder/toc.py +++ b/doc/build/builder/toc.py @@ -1,6 +1,16 @@ class TOCMixin(object): def get_current_subtoc(self, current_page_name, current_page_title): - """Return a TOC for sub-files of the current file. + """Return a TOC for sub-files and sub-elements of the current file. + + This is to provide a "contextual" navbar that shows the current page + in context of all of its siblings, not just the immediate "previous" + and "next". + + This allows a very long page with many sections to be broken + into smaller pages while not losing the navigation of the overall + section, with the added bonus that only the page-level bullets for + the current subsection are expanded, thus making for a much shorter, + "drill-down" style navigation. """ @@ -11,6 +21,15 @@ class TOCMixin(object): def _locate_nodes(nodes, level, outer=True): + # this is a lazy way of getting at all the info in a + # series of docutils nodes, with an absolute mimimal + # reliance on the actual structure of the nodes. + # we just look for refuris and the fact that a node + # is dependent on another somehow, that's it, then we + # flatten it out into a clean "tree" later. + # An official Sphinx feature/extension + # here would probably make much more use of direct + # knowledge of the structure for elem in nodes: if hasattr(elem, 'attributes'): @@ -22,10 +41,10 @@ class TOCMixin(object): if refuri is not None: name = elem.children[0].rawsource remainders = elem.children[1:] - - # not really sure what get_toc_for() does, seems - # to keep returning nodes past what is local, - # so just do a brute force filter here + # a little bit of extra filtering of when/where + # we want internal nodes vs. page-level nodes, + # this is usually not needed except in a certain + # edge case if ( not outer and refuri.startswith("#") ) or ( @@ -37,8 +56,7 @@ class TOCMixin(object): # try to embed the item-level get_toc_for() inside # the file-level get_toctree_for(), otherwise if we - # just get the full get_toctree_for(), it's enormous, - # why bother. + # just get the full get_toctree_for(), it's enormous. if outer and name == current_page_title: for ent in _locate_nodes([local_tree], level + 1, False): yield ent @@ -59,13 +77,20 @@ class TOCMixin(object): stack.append(new_collection) elif level < levels[-1]: while levels and level < levels[-1]: - stack.pop(-1) levels.pop(-1) + if level > levels[-1]: + levels.append(level) + else: + stack.pop(-1) stack[-1].append((refuri, name)) return stack def _render_nodes(stack, searchfor, level=0, nested_element=False): + # this is me being lazy about dealing with docutils renderers, + # and just programmatically rendering out. A real Sphinx + # extension / feature would obviously need to use the idiomatic + # docutils renderers. if stack: indent = " " * level printing = nested_element or searchfor in stack @@ -78,15 +103,19 @@ class TOCMixin(object): if not stack or isinstance(stack[0], tuple): if printing: if as_links: - yield "%s<li><a href='%s'>%s</a></li>" % ((indent,) + elem) + yield "%s<li><a href='%s'>%s</a></li>" % ( + (indent,) + elem) else: - yield "%s<li><strong>%s</strong></li>" % (indent, elem[1]) + yield "%s<li><strong>%s</strong></li>" % ( + indent, elem[1]) elif isinstance(stack[0], list): if printing: if as_links: - yield "%s<li><a href='%s'>%s</a>" % ((indent,) + elem) + yield "%s<li><a href='%s'>%s</a>" % ( + (indent,) + elem) else: - yield "%s<li><strong>%s</strong>" % (indent, elem[1]) + yield "%s<li><strong>%s</strong>" % ( + indent, elem[1]) for sub in _render_nodes( stack[0], searchfor, level=level + 1, @@ -98,7 +127,8 @@ class TOCMixin(object): elif isinstance(elem, list): for sub in _render_nodes( elem, searchfor, - level=level + 1, nested_element=nested_element): + level=level + 1, + nested_element=nested_element): yield sub if printing: yield (" " * level) + "</ul>" diff --git a/doc/build/conf.py b/doc/build/conf.py index 5277134e7..32955f68a 100644 --- a/doc/build/conf.py +++ b/doc/build/conf.py @@ -41,6 +41,7 @@ extensions = [ 'builder.mako', 'builder.sqlformatter', 'builder.viewsource', + 'builder.scss' ] # Add any paths that contain templates here, relative to this directory. @@ -74,6 +75,21 @@ changelog_render_pullreq = { changelog_render_changeset = "http://www.sqlalchemy.org/trac/changeset/%s" +autodocmods_convert_modname = { + "sqlalchemy.sql.sqltypes": "sqlalchemy.types", + "sqlalchemy.sql.type_api": "sqlalchemy.types", + "sqlalchemy.sql.schema": "sqlalchemy.schema", + "sqlalchemy.sql.elements": "sqlalchemy.sql.expression", + "sqlalchemy.sql.selectable": "sqlalchemy.sql.expression", + "sqlalchemy.sql.dml": "sqlalchemy.sql.expression", + "sqlalchemy.sql.ddl": "sqlalchemy.schema", + "sqlalchemy.sql.base": "sqlalchemy.sql.expression" +} + +autodocmods_convert_modname_w_class = { + ("sqlalchemy.engine.interfaces", "Connectable"): "sqlalchemy.engine", + ("sqlalchemy.sql.base", "DialectKWArgs"): "sqlalchemy.sql.base", +} # The encoding of source files. #source_encoding = 'utf-8-sig' @@ -97,6 +113,8 @@ release = "1.0.0" release_date = "Not released" site_base = os.environ.get("RTD_SITE_BASE", "http://www.sqlalchemy.org") +site_adapter_template = "docs_adapter.mako" +site_adapter_py = "docs_adapter.py" # arbitrary number recognized by builders.py, incrementing this # will force a rebuild diff --git a/doc/build/static/docs.css b/doc/build/static/docs.scss index e854d34c2..8597a993f 100644 --- a/doc/build/static/docs.css +++ b/doc/build/static/docs.scss @@ -1,11 +1,23 @@ +$primary-font-family: Verdana, sans-serif; +$header-font-family: Helvetica, Arial, sans-serif; +$top-header-font-family: Tahoma,Geneva,sans-serif; +$primary-background-color: #FDFBFC; +$topmost-header-color: #EBEBEE; +$popout-color: #FBFBEE; +$sidebar-color: #EFEFEF; +$sidebar-header-background-color: #DDDDDD; +$sidebar-header-color: #222222; +$notebox-background-color: #EEFFEF; +$border-style: 1px solid #CCC; + /* global */ .body-background { - background-color: #FDFBFC; + background-color: $primary-background-color; } body { - background-color: #FDFBFC; + background-color: $primary-background-color; margin:0 38px; color:#333333; } @@ -22,12 +34,10 @@ form { /* hyperlinks */ a:link, a:visited, a:active { - /*color:#0000FF;*/ color: #990000; } a:hover { color: #FF0000; - /*color:#700000;*/ text-decoration:underline; } @@ -72,26 +82,28 @@ a.headerlink:hover { /* header/footer elements */ -#docs-header h1 { - font-size:20px; - color: #222222; - margin: 0; - padding: 0; -} - #docs-header { - font-family:Verdana,sans-serif; + font-family: $primary-font-family; font-size:.9em; position: relative; + + h1 { + font-size: 20px; + color: #222222; + margin: 4px 0px; + padding: 5px 5px; + background-color: $topmost-header-color; + border: $border-style; + } } #docs-sidebar-popout, #docs-bottom-navigation, #index-nav { - font-family: Verdana, sans-serif; - background-color: #FBFBEE; - border: solid 1px #CCC; + font-family: $primary-font-family; + background-color: $popout-color; + border: $border-style; font-size:.8em; } @@ -116,12 +128,12 @@ a.headerlink:hover { #docs-version-header { position: absolute; - right: 0; - bottom: 0; + right: 8px; + bottom: 8px; } .docs-navigation-links { - font-family:Verdana,sans-serif; + font-family: $primary-font-family; } #docs-bottom-navigation { @@ -137,7 +149,7 @@ a.headerlink:hover { #docs-header h1, #docs-top-navigation h1, #docs-top-navigation h2 { - font-family:Tahoma,Geneva,sans-serif; + font-family: $top-header-font-family; font-weight:normal; } @@ -178,10 +190,7 @@ a.headerlink:hover { #docs-sidebar, #index-nav { - /*font-family: helvetica, arial, sans-serif; - font-size:.9em;*/ - - font-family: Verdana, sans-serif; + font-family: $primary-font-family; font-size:.85em; line-height:1.5em; @@ -222,10 +231,10 @@ a.headerlink:hover { #docs-sidebar { font-size:.85em; - border: solid 1px #CCC; + border: $border-style; z-index: 3; - background-color: #EFEFEF; + background-color: $sidebar-color; } #index-nav { @@ -302,9 +311,9 @@ a.headerlink:hover { #docs-sidebar h3, #docs-sidebar h4 { - background-color: #DDDDDD; - color: #222222; - font-family: Verdana,sans-serif; + background-color: $sidebar-header-background-color; + color: $sidebar-header-color; + font-family: $primary-font-family; font-size: 1.1em; font-weight: normal; margin: 10px 0 0 -15px; @@ -318,7 +327,7 @@ a.headerlink:hover { } #docs-sidebar h3 a, #docs-sidebar h4 a { - color: #222222; + color: $sidebar-header-color; } #docs-sidebar ul { margin: 10px 10px 10px 0px; @@ -341,7 +350,7 @@ a.headerlink:hover { background-color:#FFFFFF; padding:1px 10px 10px 10px; - border: solid 1px #CCC; + border: $border-style; margin-top:10px; } @@ -354,7 +363,7 @@ a.headerlink:hover { #docs-body h2, #docs-body h3, #docs-body h4 { - font-family:Helvetica, Arial, sans-serif; + font-family: $header-font-family; } #docs-body #sqlalchemy-documentation h1 { @@ -395,7 +404,7 @@ a.headerlink:hover { #docs-container pre { background-color: #f0f0f0; - border: solid 1px #ccc; + border: $border-style; box-shadow: 2px 2px 3px #DFDFDF; padding:10px; margin: 5px 0px 5px 0px; @@ -405,7 +414,7 @@ a.headerlink:hover { .popup_sql, .show_sql { - background-color: #FBFBEE; + background-color: $popout-color; padding:5px 10px; margin:10px -5px; border:1px dashed; @@ -415,7 +424,7 @@ a.headerlink:hover { #docs-container .sql_link { font-weight:normal; - font-family: arial, sans-serif; + font-family: helvetica, arial, sans-serif; font-size:.9em; text-transform: uppercase; color:#990000; @@ -458,7 +467,7 @@ div.section { } div.note, div.warning, p.deprecated, div.topic, div.admonition { - background-color:#EEFFEF; + background-color:$notebox-background-color; } .footnote { @@ -474,7 +483,7 @@ div.faq ul { } div.admonition, div.topic, .deprecated, .versionadded, .versionchanged { - border:1px solid #CCCCCC; + border: $border-style; padding:5px 10px; font-size:.9em; margin-top:5px; @@ -511,7 +520,7 @@ p.sidebar-title { div.inherited-member { - border:1px solid #CCCCCC; + border: $border-style; padding:5px 5px; font-size:.9em; box-shadow: 2px 2px 3px #DFDFDF; @@ -652,22 +661,3 @@ div .version-warning { background:#FFBBBB; } -/*div .event-signatures { - background-color:#F0F0FD; - padding:0 10px; - border:1px solid #BFBFBF; -}*/ - -/*dl div.floatything { - display:none; - position:fixed; - top:25px; - left:40px; - font-size:.95em; - font-weight: bold; - border:1px solid; - background-color: #FFF; -} -dl:hover div.floatything { - display:block; -}*/ diff --git a/doc/build/templates/layout.mako b/doc/build/templates/layout.mako index c0bf2bf9f..4520a43cc 100644 --- a/doc/build/templates/layout.mako +++ b/doc/build/templates/layout.mako @@ -172,7 +172,7 @@ withsidebar = bool(toc) and current_page_name != 'index' <div id="docs-sidebar"> - <h3><a href="#">\ + <h3><a href="${parents[-1]['link'] if parents else '#'}">\ <%block name="show_title"> % if parents: ${parents[-1]['title']} @@ -182,11 +182,6 @@ withsidebar = bool(toc) and current_page_name != 'index' </%block> </a></h3> - <% - #if title == 'Schema Definition Language': - # import pdb - # pdb.set_trace() - %> % if parents: ${parent_toc(current_page_name, title)} % else: |