Add oauth-only view of api docs.

This commit is contained in:
Logan Hanks
2012-09-25 16:00:42 -07:00
parent f382f63236
commit 22b49edc3c
4 changed files with 151 additions and 31 deletions

View File

@@ -260,6 +260,8 @@ def make_map():
mc('/dev', controller='redirect', action='redirect', dest='/dev/api')
mc('/dev/api', controller='apidocs', action='docs')
mc('/dev/api/:mode', controller='apidocs', action='docs',
requirements=dict(mode="oauth"))
mc("/button_info", controller="api", action="info", limit=1)

View File

@@ -31,6 +31,7 @@ from pylons.i18n import _
from reddit_base import RedditController
from r2.lib.utils import Storage
from r2.lib.pages import BoringPage, ApiHelp
from r2.controllers.validator import validate, VOneOf
# API sections displayed in the documentation page.
# Each section can have a title and a markdown-formatted description.
@@ -96,7 +97,7 @@ def api_doc(section, **kwargs):
class ApidocsController(RedditController):
@staticmethod
def docs_from_controller(controller, url_prefix='/api'):
def docs_from_controller(controller, url_prefix='/api', oauth_only=False):
"""
Examines a controller for documentation. A dictionary index of
sections containing dictionaries of URLs is returned. For each URL, a
@@ -142,12 +143,22 @@ class ApidocsController(RedditController):
# add every variant to the index -- the templates will filter
# out variants in the long-form documentation
for variant in chain([uri], docs.get('uri_variants', [])):
api_docs[docs['section']][variant][method] = docs
if oauth_only:
if not docs['oauth_scopes']:
continue
for scope in docs['oauth_scopes']:
for variant in chain([uri],
docs.get('uri_variants', [])):
api_docs[scope][variant][method] = docs
else:
for variant in chain([uri], docs.get('uri_variants', [])):
api_docs[docs['section']][variant][method] = docs
return api_docs
def GET_docs(self):
@validate(
mode=VOneOf('mode', options=('methods', 'oauth'), default='methods'))
def GET_docs(self, mode):
# controllers to gather docs from.
from r2.controllers.api import ApiController, ApiminimalController
from r2.controllers.apiv1 import APIv1Controller
@@ -166,14 +177,23 @@ class ApidocsController(RedditController):
# merge documentation info together.
api_docs = defaultdict(dict)
oauth_index = defaultdict(set)
for controller, url_prefix in api_controllers:
for section, contents in self.docs_from_controller(controller, url_prefix).iteritems():
controller_docs = self.docs_from_controller(controller, url_prefix,
mode == 'oauth')
for section, contents in controller_docs.iteritems():
api_docs[section].update(contents)
for variant, method_dict in contents.iteritems():
for method, docs in method_dict.iteritems():
for scope in docs['oauth_scopes']:
oauth_index[scope].add((section, variant, method))
return BoringPage(
_('api documentation'),
content=ApiHelp(
api_docs=api_docs
api_docs=api_docs,
oauth_index=oauth_index,
mode=mode,
),
css_class="api-help",
show_sidebar=False,

View File

@@ -5828,6 +5828,41 @@ tr.gold-accent + tr > td {
text-decoration: underline;
}
.api-help .toc .mode-selector {
display: inline-block;
font-size: x-small;
border-radius: 5px;
border: 1px solid #888;
margin-top: 6px;
vertical-align: middle;
}
.api-help .toc .mode-selector .mode {
display: inline-block;
margin: 2px;
padding-top: 2px;
padding-bottom: 3px;
border-radius: 3px;
text-align: center;
width: 107px;
color: #ddd;
}
.api-help .toc .mode-selector .mode:hover {
background-color: #ccc;
color: black;
text-decoration: none;
}
.api-help .toc .mode-selector .mode-current {
color: black;
background-color: #eee;
}
.api-help .toc .mode-selector .mode-current:hover {
background-color: #ddd;
}
.api-help em.placeholder {
font-style: italic;
font-weight: normal;
@@ -5882,6 +5917,13 @@ tr.gold-accent + tr > td {
border-bottom: 1px solid #aaa;
}
.api-help .methods h2 .scope-id {
margin-left: 1em;
font-size: small;
font-weight: normal;
font-style: italic;
}
.api-help .endpoint .info {
padding-left: 1em;
border-left: 1px solid #ddd;

View File

@@ -24,11 +24,83 @@
import re
from r2.lib.filters import safemarkdown
from r2.controllers.api_docs import section_info
from r2.models.token import OAuth2Scope
%>
<%def name="api_method_id(uri, method)">${method}_${uri.replace('/', '_').strip('_')}</%def>
<%def name="api_uri(uri)">${unsafe(re.sub(r'{(\w+)}', r'<em class="placeholder">\1</em>', uri))}</%def>
<%def name="mode_selector(current_mode)">
<span class="mode-selector">
<a class="mode ${'mode-current' if current_mode == 'section' else ''}"
href="/dev/api">by section</a>
<a class="mode ${'mode-current' if current_mode == 'oauth' else ''}"
href="/dev/api/oauth">by oauth scope</a>
</span>
</%def>
<%def name="api_method_toc(api)">
<strong>API methods</strong>
${mode_selector('section')}
<ul>
%for section in sorted(api):
<li>
<a href="#section_${section}" class="section">${section_info[section]['title']}</a>
<ul>
%for uri in sorted(api[section]):
<%
methods = sorted(api[section][uri].keys())
has_oauth = any(api[section][uri][method]['oauth_scopes']
for method in methods)
%>
<li class="${'supports-oauth' if has_oauth else ''}">
<a href="#${api_method_id(uri, methods[0])}">${api_uri(uri)}</a>
</li>
%endfor
</ul>
</li>
%endfor
</ul>
</%def>
<%def name="oauth_toc(api, oauth_index)">
<strong>API methods</strong>
${mode_selector('oauth')}
<ul>
%for scope, keys in sorted(oauth_index.iteritems()):
<li>
<a href="#scope_${scope}" class="section">${scope}</a>
<ul>
%for section, uri, method in sorted(keys):
<li>
<a href="#${api_method_id(uri, method)}">${api_uri(uri)}</a>
</li>
%endfor
</ul>
</li>
%endfor
</ul>
</%def>
<%def name="section_header(section)">
<h2 id="section_${section}">${section_info[section]['title']}</h2>
%if 'description' in section_info[section]:
<div class="description">
${unsafe(safemarkdown(section_info[section]['description']))}
</div>
%endif
</%def>
<%def name="scope_header(scope)">
<h2 id="scope_${scope}">
${OAuth2Scope.scope_info[scope]['name']}
<span class="scope-id">${scope}</span>
</h2>
<div class="description">
${unsafe(safemarkdown(OAuth2Scope.scope_info[scope]['description']))}
</div>
</%def>
<%
api = thing.api_docs
%>
@@ -38,26 +110,11 @@
<div class="toc">
<ul>
<li>
<strong>API methods</strong>
<ul>
%for section in sorted(api):
<li>
<a href="#section_${section}" class="section">${section_info[section]['title']}</a>
<ul>
%for uri in sorted(api[section]):
<%
methods = sorted(api[section][uri].keys())
has_oauth = any(api[section][uri][method]['oauth_scopes']
for method in methods)
%>
<li class="${'supports-oauth' if has_oauth else ''}">
<a href="#${api_method_id(uri, methods[0])}">${api_uri(uri)}</a>
</li>
%endfor
</ul>
</li>
%endfor
</ul>
%if thing.mode == "oauth":
${oauth_toc(thing.api_docs, thing.oauth_index)}
%else:
${api_method_toc(thing.api_docs)}
%endif
</li>
</ul>
</div>
@@ -73,11 +130,10 @@
<div class="section methods">
%for section in sorted(api):
<h2 id="section_${section}">${section_info[section]['title']}</h2>
%if 'description' in section_info[section]:
<div class="description">
${unsafe(safemarkdown(section_info[section]['description']))}
</div>
%if thing.mode == 'oauth':
${scope_header(section)}
%else:
${section_header(section)}
%endif
%for uri in sorted(api[section]):
%for method in sorted(api[section][uri]):