Fix lack of top level methods from a service.
This commit is contained in:
@@ -91,6 +91,7 @@ def build(serviceName, version,
|
|||||||
return build_from_document(content, discoveryServiceUrl, future,
|
return build_from_document(content, discoveryServiceUrl, future,
|
||||||
http, developerKey, model, requestBuilder)
|
http, developerKey, model, requestBuilder)
|
||||||
|
|
||||||
|
|
||||||
def build_from_document(
|
def build_from_document(
|
||||||
service,
|
service,
|
||||||
base,
|
base,
|
||||||
@@ -105,8 +106,8 @@ def build_from_document(
|
|||||||
base: string, base URI for all HTTP requests, usually the discovery URI
|
base: string, base URI for all HTTP requests, usually the discovery URI
|
||||||
future: string, discovery document with future capabilities
|
future: string, discovery document with future capabilities
|
||||||
auth_discovery: dict, information about the authentication the API supports
|
auth_discovery: dict, information about the authentication the API supports
|
||||||
http: httplib2.Http, An instance of httplib2.Http or something that acts like
|
http: httplib2.Http, An instance of httplib2.Http or something that acts
|
||||||
it that HTTP requests will be made through.
|
like it that HTTP requests will be made through.
|
||||||
developerKey: string, Key for controlling API usage, generated
|
developerKey: string, Key for controlling API usage, generated
|
||||||
from the API Console.
|
from the API Console.
|
||||||
model: Model class instance that serializes and
|
model: Model class instance that serializes and
|
||||||
@@ -116,45 +117,26 @@ def build_from_document(
|
|||||||
|
|
||||||
service = simplejson.loads(service)
|
service = simplejson.loads(service)
|
||||||
base = urlparse.urljoin(base, service['restBasePath'])
|
base = urlparse.urljoin(base, service['restBasePath'])
|
||||||
resources = service['resources']
|
|
||||||
if future:
|
if future:
|
||||||
doc = simplejson.loads(future)
|
future = simplejson.loads(future)
|
||||||
future = doc['resources']
|
auth_discovery = future.get('auth', {})
|
||||||
auth_discovery = doc.get('auth', {})
|
|
||||||
else:
|
else:
|
||||||
future = {}
|
future = {}
|
||||||
auth_discovery = {}
|
auth_discovery = {}
|
||||||
|
|
||||||
class Service(object):
|
resource = createResource(http, base, model, requestBuilder, developerKey,
|
||||||
"""Top level interface for a service"""
|
service, future)
|
||||||
|
|
||||||
def __init__(self, http=http):
|
def auth_method():
|
||||||
self._http = http
|
"""Discovery information about the authentication the API uses."""
|
||||||
self._baseUrl = base
|
return auth_discovery
|
||||||
self._model = model
|
|
||||||
self._developerKey = developerKey
|
|
||||||
self._requestBuilder = requestBuilder
|
|
||||||
|
|
||||||
def auth_discovery(self):
|
setattr(resource, 'auth_discovery', auth_method)
|
||||||
return auth_discovery
|
|
||||||
|
|
||||||
def createMethod(theclass, methodName, methodDesc, futureDesc):
|
return resource
|
||||||
|
|
||||||
def method(self):
|
|
||||||
return createResource(self._http, self._baseUrl, self._model,
|
|
||||||
self._requestBuilder, methodName,
|
|
||||||
self._developerKey, methodDesc, futureDesc)
|
|
||||||
|
|
||||||
setattr(method, '__doc__', 'A description of how to use this function')
|
|
||||||
setattr(method, '__is_resource__', True)
|
|
||||||
setattr(theclass, methodName, method)
|
|
||||||
|
|
||||||
for methodName, methodDesc in resources.iteritems():
|
|
||||||
createMethod(Service, methodName, methodDesc, future.get(methodName, {}))
|
|
||||||
return Service()
|
|
||||||
|
|
||||||
|
|
||||||
def createResource(http, baseUrl, model, requestBuilder, resourceName,
|
def createResource(http, baseUrl, model, requestBuilder,
|
||||||
developerKey, resourceDesc, futureDesc):
|
developerKey, resourceDesc, futureDesc):
|
||||||
|
|
||||||
class Resource(object):
|
class Resource(object):
|
||||||
@@ -322,8 +304,8 @@ def createResource(http, baseUrl, model, requestBuilder, resourceName,
|
|||||||
|
|
||||||
def method(self):
|
def method(self):
|
||||||
return createResource(self._http, self._baseUrl, self._model,
|
return createResource(self._http, self._baseUrl, self._model,
|
||||||
self._requestBuilder, methodName,
|
self._requestBuilder, self._developerKey,
|
||||||
self._developerKey, methodDesc, futureDesc)
|
methodDesc, futureDesc)
|
||||||
|
|
||||||
setattr(method, '__doc__', 'A description of how to use this function')
|
setattr(method, '__doc__', 'A description of how to use this function')
|
||||||
setattr(method, '__is_resource__', True)
|
setattr(method, '__is_resource__', True)
|
||||||
@@ -335,10 +317,10 @@ def createResource(http, baseUrl, model, requestBuilder, resourceName,
|
|||||||
else:
|
else:
|
||||||
future = {}
|
future = {}
|
||||||
createMethod(Resource, methodName, methodDesc,
|
createMethod(Resource, methodName, methodDesc,
|
||||||
future.get(methodName, {}))
|
future)
|
||||||
|
|
||||||
# Add <m>_next() methods to Resource
|
# Add <m>_next() methods to Resource
|
||||||
if futureDesc:
|
if futureDesc and 'methods' in futureDesc:
|
||||||
for methodName, methodDesc in futureDesc['methods'].iteritems():
|
for methodName, methodDesc in futureDesc['methods'].iteritems():
|
||||||
if 'next' in methodDesc and methodName in resourceDesc['methods']:
|
if 'next' in methodDesc and methodName in resourceDesc['methods']:
|
||||||
createNextMethod(Resource, methodName + "_next",
|
createNextMethod(Resource, methodName + "_next",
|
||||||
|
|||||||
@@ -79,10 +79,12 @@ class Credentials(object):
|
|||||||
"""
|
"""
|
||||||
_abstract()
|
_abstract()
|
||||||
|
|
||||||
|
|
||||||
class Flow(object):
|
class Flow(object):
|
||||||
"""Base class for all Flow objects."""
|
"""Base class for all Flow objects."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class OAuthCredentials(Credentials):
|
class OAuthCredentials(Credentials):
|
||||||
"""Credentials object for OAuth 1.0a
|
"""Credentials object for OAuth 1.0a
|
||||||
"""
|
"""
|
||||||
@@ -254,4 +256,3 @@ class FlowThreeLegged(Flow):
|
|||||||
oauth_params['oauth_token_secret'])
|
oauth_params['oauth_token_secret'])
|
||||||
|
|
||||||
return OAuthCredentials(consumer, token, self.user_agent)
|
return OAuthCredentials(consumer, token, self.user_agent)
|
||||||
|
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ DEVELOPER_KEY = 'AIzaSyACZJW4JwcWwz5taR2gjIMNQrtgDLfILPc'
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Get and print a feed of public products in the United States mathing a text
|
"""Get and print a feed of public products in the United States mathing a
|
||||||
search query for 'digital camera' and grouped by the 8 top brands.
|
text search query for 'digital camera' and grouped by the 8 top brands.
|
||||||
|
|
||||||
The list method of the resource should be called with the "crowdBy" parameter.
|
The list method of the resource should be called with the "crowdBy"
|
||||||
Each parameter should be designed as <attribute>:<occurence>, where
|
parameter. Each parameter should be designed as <attribute>:<occurence>,
|
||||||
<occurrence> is the number of that <attribute> that will be used. For
|
where <occurrence> is the number of that <attribute> that will be used. For
|
||||||
example, to crowd by the 5 top brands, the parameter would be "brand:5". The
|
example, to crowd by the 5 top brands, the parameter would be "brand:5". The
|
||||||
possible rules for crowding are currently:
|
possible rules for crowding are currently:
|
||||||
|
|
||||||
|
|||||||
@@ -23,9 +23,10 @@ def main():
|
|||||||
The "|" operator can be used to search for alternative search terms, for
|
The "|" operator can be used to search for alternative search terms, for
|
||||||
example: q = 'banana|apple' will search for bananas or apples.
|
example: q = 'banana|apple' will search for bananas or apples.
|
||||||
|
|
||||||
Search phrases such as those containing spaces can be specified by surrounding
|
Search phrases such as those containing spaces can be specified by
|
||||||
them with double quotes, for example q='"mp3 player"'. This can be useful when
|
surrounding them with double quotes, for example q='"mp3 player"'. This can
|
||||||
combining with the "|" operator such as q = '"mp3 player"|ipod'.
|
be useful when combining with the "|" operator such as q = '"mp3
|
||||||
|
player"|ipod'.
|
||||||
"""
|
"""
|
||||||
client = build('shopping', SHOPPING_API_VERSION, developerKey=DEVELOPER_KEY)
|
client = build('shopping', SHOPPING_API_VERSION, developerKey=DEVELOPER_KEY)
|
||||||
resource = client.products()
|
resource = client.products()
|
||||||
|
|||||||
@@ -16,16 +16,17 @@ def main():
|
|||||||
"""Get and print a histogram of the top 15 brand distribution for a search
|
"""Get and print a histogram of the top 15 brand distribution for a search
|
||||||
query.
|
query.
|
||||||
|
|
||||||
Histograms are created by using the "Facets" functionality of the API. A Facet
|
Histograms are created by using the "Facets" functionality of the API. A
|
||||||
is a view of a certain property of products, containing a number of buckets,
|
Facet is a view of a certain property of products, containing a number of
|
||||||
one for each value of that property. Or concretely, for a parameter such as
|
buckets, one for each value of that property. Or concretely, for a parameter
|
||||||
"brand" of a product, the facets would include a facet for brand, which would
|
such as "brand" of a product, the facets would include a facet for brand,
|
||||||
contain a number of buckets, one for each brand returned in the result.
|
which would contain a number of buckets, one for each brand returned in the
|
||||||
|
result.
|
||||||
|
|
||||||
A bucket contains either a value and a count, or a value and a range. In the
|
A bucket contains either a value and a count, or a value and a range. In the
|
||||||
simple case of a value and a count for our example of the "brand" property,
|
simple case of a value and a count for our example of the "brand" property,
|
||||||
the value would be the brand name, eg "sony" and the count would be the number
|
the value would be the brand name, eg "sony" and the count would be the
|
||||||
of results in the search.
|
number of results in the search.
|
||||||
"""
|
"""
|
||||||
client = build('shopping', SHOPPING_API_VERSION, developerKey=DEVELOPER_KEY)
|
client = build('shopping', SHOPPING_API_VERSION, developerKey=DEVELOPER_KEY)
|
||||||
resource = client.products()
|
resource = client.products()
|
||||||
|
|||||||
@@ -15,11 +15,12 @@ DEVELOPER_KEY = 'AIzaSyACZJW4JwcWwz5taR2gjIMNQrtgDLfILPc'
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Get and print a feed of public products in the United States mathing a text
|
"""Get and print a feed of public products in the United States mathing a
|
||||||
search query for 'digital camera' ranked by ascending price.
|
text search query for 'digital camera' ranked by ascending price.
|
||||||
|
|
||||||
The list method for the resource should be called with the "rankBy" parameter.
|
The list method for the resource should be called with the "rankBy"
|
||||||
5 parameters to rankBy are currently supported by the API. They are:
|
parameter. 5 parameters to rankBy are currently supported by the API. They
|
||||||
|
are:
|
||||||
|
|
||||||
"relevancy"
|
"relevancy"
|
||||||
"modificationTime:ascending"
|
"modificationTime:ascending"
|
||||||
@@ -33,8 +34,8 @@ def main():
|
|||||||
"""
|
"""
|
||||||
client = build('shopping', SHOPPING_API_VERSION, developerKey=DEVELOPER_KEY)
|
client = build('shopping', SHOPPING_API_VERSION, developerKey=DEVELOPER_KEY)
|
||||||
resource = client.products()
|
resource = client.products()
|
||||||
# The rankBy parameter to the list method causes results to be ranked, in this
|
# The rankBy parameter to the list method causes results to be ranked, in
|
||||||
# case by ascending price.
|
# this case by ascending price.
|
||||||
request = resource.list(source='public', country='US', q=u'digital camera',
|
request = resource.list(source='public', country='US', q=u'digital camera',
|
||||||
rankBy='price:ascending')
|
rankBy='price:ascending')
|
||||||
response = request.execute()
|
response = request.execute()
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
#
|
#
|
||||||
# Copyright 2010 Google Inc. All Rights Reserved.
|
# Copyright 2010 Google Inc. All Rights Reserved.
|
||||||
|
|
||||||
"""Query that is restricted by a parameter against the public shopping search API"""
|
"""Query that is restricted by a parameter against the public shopping search
|
||||||
|
API"""
|
||||||
|
|
||||||
import pprint
|
import pprint
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,20 @@
|
|||||||
"description": "Zoo API used for testing",
|
"description": "Zoo API used for testing",
|
||||||
"restBasePath": "/zoo",
|
"restBasePath": "/zoo",
|
||||||
"rpcPath": "/rpc",
|
"rpcPath": "/rpc",
|
||||||
|
"methods": {
|
||||||
|
"query": {
|
||||||
|
"restPath": "query",
|
||||||
|
"rpcMethod": "bigquery.query",
|
||||||
|
"httpMethod": "GET",
|
||||||
|
"parameters": {
|
||||||
|
"q": {
|
||||||
|
"restParameterType": "query",
|
||||||
|
"required": false,
|
||||||
|
"repeated": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"resources": {
|
"resources": {
|
||||||
"my": {
|
"my": {
|
||||||
"resources": {
|
"resources": {
|
||||||
|
|||||||
@@ -113,6 +113,14 @@ class Discovery(unittest.TestCase):
|
|||||||
q = parse_qs(parsed[4])
|
q = parse_qs(parsed[4])
|
||||||
self.assertEqual(q['max-results'], ['5'])
|
self.assertEqual(q['max-results'], ['5'])
|
||||||
|
|
||||||
|
def test_top_level_functions(self):
|
||||||
|
self.http = HttpMock('zoo.json', {'status': '200'})
|
||||||
|
zoo = build('zoo', 'v1', self.http)
|
||||||
|
self.assertTrue(getattr(zoo, 'query'))
|
||||||
|
request = zoo.query(q="foo")
|
||||||
|
parsed = urlparse.urlparse(request.uri)
|
||||||
|
q = parse_qs(parsed[4])
|
||||||
|
self.assertEqual(q['q'], ['foo'])
|
||||||
|
|
||||||
|
|
||||||
class Next(unittest.TestCase):
|
class Next(unittest.TestCase):
|
||||||
|
|||||||
Reference in New Issue
Block a user