docs(scopes): added CLI scope documentation

In addition to that, they can now be set as well.
Unified generation of the 'default' scope.
This commit is contained in:
Sebastian Thiel
2015-04-12 17:15:55 +02:00
parent 310c81f19c
commit 49c4a4101e
8 changed files with 102 additions and 47 deletions

View File

@@ -16,7 +16,7 @@ make:
templates:
- source: ../LICENSE.md
- source: ../Cargo.toml
- source: docs/commands.yml
- source: docs/commands.md
- source: mkdocs.yml
- source: README.md
- source: main.rs

View File

@@ -10,7 +10,7 @@
CALL_BUILDER_MARKERT_TRAIT, pass_through, markdown_rust_block, parts_from_params,
DELEGATE_PROPERTY_NAME, struct_type_bounds_s, supports_scopes, scope_url_to_variant,
re_find_replacements, ADD_PARAM_FN, ADD_PARAM_MEDIA_EXAMPLE, upload_action_fn, METHODS_RESOURCE,
method_name_to_variant, unique_type_name, size_to_bytes)
method_name_to_variant, unique_type_name, size_to_bytes, method_default_scope)
def get_parts(part_prop):
if not part_prop:
@@ -427,15 +427,7 @@ match result {
auth_call = 'self.hub.auth.borrow_mut()'
if supports_scopes(auth):
all_scopes = sorted(auth.oauth2.scopes.keys())
default_scope = all_scopes[0]
if m.httpMethod in ('HEAD', 'GET', 'OPTIONS', 'TRACE'):
for scope in all_scopes:
if 'readonly' in scope:
default_scope = scope
break
# end for each scope
# end try to find read-only default scope
default_scope = method_default_scope(m)
# end handle default scope
# s = '{foo}' -> ('{foo}', 'foo') -> (find_this, replace_with)

View File

@@ -0,0 +1,38 @@
<%namespace name="util" file="../../lib/util.mako"/>\
<%
from util import (hash_comment, new_context, method_default_scope)
from cli import (subcommand_md_filename, new_method_context, SPLIT_START, SPLIT_END, pretty, SCOPE_FLAG,
mangle_subcommand)
c = new_context(schemas, resources, context.get('methods'))
%>\
% for resource in sorted(c.rta_map.keys()):
% for method in sorted(c.rta_map[resource]):
<%
mc = new_method_context(resource, method, c)
%>\
${SPLIT_START} ${subcommand_md_filename(resource, method)}
# ${pretty(resource)}: ${pretty(method)}
% if mc.m.description:
${mc.m.description}
% endif # show method description
% if mc.m.get('scopes'):
# Scopes
You will need authorization for \
% if len(mc.m.scopes) > 1:
at least one of the following scopes to make a valid call:
% for s in mc.m.scopes:
* *${s}*
% endfor
% else:
the *${mc.m.scopes[0]}* scope to make a valid call.
% endif # len(scopes) > 1
If unset, the scope for this method defaults to *${method_default_scope(mc.m)}*.
You can set the scope for this method like this: `${util.program_name()} --${SCOPE_FLAG} <scope> ${mangle_subcommand(resource)} ${mangle_subcommand(method)} ...`
% endif # have method scopes
${SPLIT_END}
% endfor # each method
% endfor # each resource

View File

@@ -1,16 +0,0 @@
<%namespace name="util" file="../../lib/util.mako"/>\
<%
from util import (hash_comment, new_context)
from cli import (subcommand_md_filename, SPLIT_START, SPLIT_END)
c = new_context(schemas, resources, context.get('methods'))
%>\
% for resource in sorted(c.rta_map.keys()):
% for method in sorted(c.rta_map[resource]):
${SPLIT_START} ${subcommand_md_filename(resource, method)}
${resource.upper()} DOCS
${method.upper()}
${SPLIT_END}
% endfor # each method
% endfor # each resource

View File

@@ -2,6 +2,7 @@ import util
import os
import re
import collections
SPLIT_START = '>>>>>>>'
SPLIT_END = '<<<<<<<'
@@ -11,12 +12,34 @@ STRUCT_FLAG = 'r'
UPLOAD_FLAG = 'u'
OUTPUT_FLAG = 'o'
VALUE_ARG = 'v'
SCOPE_FLAG = 'scope'
CONFIG_DIR = '~/.google-service-cli'
re_splitters = re.compile(r"%s ([\w\-\.]+)\n(.*?)\n%s" % (SPLIT_START, SPLIT_END), re.MULTILINE|re.DOTALL)
MethodContext = collections.namedtuple('MethodContext', ['m', 'response_schema', 'params', 'request_value',
'media_params' ,'required_props', 'optional_props',
'part_prop'])
def new_method_context(resource, method, c):
m = c.fqan_map[util.to_fqan(c.rtc_map[resource], resource, method)]
response_schema = util.method_response(c, m)
params, request_value = util.build_all_params(c, m)
media_params = util.method_media_params(m)
required_props, optional_props, part_prop = util.organize_params(params, request_value)
return MethodContext(m, response_schema, params, request_value, media_params,
required_props, optional_props, part_prop)
def pretty(n):
return ' '.join(s.capitalize() for s in mangle_subcommand(n).split('-'))
# transform name to be a suitable subcommand
def mangle_subcommand(name):
return util.camel_to_under(util.singular(name)).replace('_', '-').replace('.', '-')
return util.camel_to_under(name).replace('_', '-').replace('.', '-')
# transform the resource name into a suitable filename to contain the markdown documentation for it

View File

@@ -1,7 +1,8 @@
<%namespace name="util" file="../../lib/util.mako"/>\
<%!
from util import (put_and, to_fqan, method_response, build_all_params, organize_params, method_media_params)
from cli import (mangle_subcommand, PARAM_FLAG, STRUCT_FLAG, UPLOAD_FLAG, OUTPUT_FLAG, VALUE_ARG)
from util import (put_and, supports_scopes)
from cli import (mangle_subcommand, new_method_context, PARAM_FLAG, STRUCT_FLAG, UPLOAD_FLAG, OUTPUT_FLAG, VALUE_ARG,
CONFIG_DIR, SCOPE_FLAG)
v_arg = '<%s>' % VALUE_ARG
file_arg = '<file>'
@@ -20,41 +21,37 @@ Usage:
% for resource in sorted(c.rta_map.keys()):
% for method in sorted(c.rta_map[resource]):
<%
m = c.fqan_map[to_fqan(c.rtc_map[resource], resource, method)]
response_schema = method_response(c, m)
params, request_value = build_all_params(c, m)
media_params = method_media_params(m)
required_props, optional_props, part_prop = organize_params(params, request_value)
mc = new_method_context(resource, method, c)
args = list()
if optional_props or parameters is not UNDEFINED:
if mc.optional_props or parameters is not UNDEFINED:
args.append('[-%s %s]...' % (PARAM_FLAG, v_arg))
param_used = True
# end paramters
if request_value:
if mc.request_value:
args.append('-%s %s...' % (STRUCT_FLAG, v_arg))
struct_used = True
# end request_value
if media_params:
upload_protocols = [mp.protocol for mp in media_params]
if mc.media_params:
upload_protocols = [mp.protocol for mp in mc.media_params]
mode = '|'.join(upload_protocols)
if len(media_params) > 1:
if len(mc.media_params) > 1:
mode = '(%s)' % mode
args.append('-%s %s %s %s' % (UPLOAD_FLAG, mode, file_arg, mime_arg))
upload_protocols_used = upload_protocols_used|set(upload_protocols)
# end upload handling
if response_schema:
if mc.response_schema:
args.append('[-%s %s]' % (OUTPUT_FLAG, out_arg))
output_used = True
# handle output
%>\
${util.program_name()} ${mangle_subcommand(resource)} ${mangle_subcommand(method)} ${' '.join(args)}
${util.program_name()} [config] ${mangle_subcommand(resource)} ${mangle_subcommand(method)} ${' '.join(args)}
% endfor # each method
% endfor # end for each resource
${util.program_name()} --help
${util.program_name()} --help
% if param_used|struct_used|output_used or upload_protocols_used:
Options:
@@ -83,6 +80,18 @@ Options:
a filepath that is to contain the received bytes.
If unset, it defaults to standard output.
% endif
% endif # any special option is used
Config:
% if supports_scopes(auth):
--${SCOPE_FLAG} <url>
Specify the authentication a method should be executed in. Each scope requires
the user to grant this application permission to use it.
If unset, it defaults to the shortest scope url for a particular method.
% endif scopes
--config-dir <folder>
A directory into which we will store our persistent data. Defaults to a user-writable
directory that we will create during the first invocation.
[default: ${CONFIG_DIR}]
");
</%def>

View File

@@ -1,11 +1,8 @@
<%
from util import (put_and, new_context)
from cli import (subcommand_md_filename, mangle_subcommand)
from cli import (subcommand_md_filename, mangle_subcommand, pretty)
c = new_context(schemas, resources, context.get('methods'))
def pretty(n):
return ' '.join(s.capitalize() for s in mangle_subcommand(n).split('-'))
%>\
<%namespace name="util" file="../lib/util.mako"/>\
site_name: ${util.canonical_name()} v${util.crate_version()}

View File

@@ -834,6 +834,18 @@ def hub_type_bounds():
def supports_scopes(auth):
return bool(auth) and bool(auth.oauth2)
# Returns th desired scope for the given method. It will use read-only scopes for read-only methods
def method_default_scope(m):
default_scope = sorted(m.scopes)[0]
if m.httpMethod in ('HEAD', 'GET', 'OPTIONS', 'TRACE'):
for scope in m.scopes:
if 'readonly' in scope:
default_scope = scope
break
# end for each scope
# end try to find read-only default scope
return default_scope
# return list of type bounds required by method builder
def mb_type_bounds():
return hub_type_bounds()