Merge lp:~leonardr/lazr.restful/version-descriptions into lp:lazr.restful

Proposed by Leonard Richardson
Status: Merged
Approved by: Gary Poster
Approved revision: 125
Merged at revision: not available
Proposed branch: lp:~leonardr/lazr.restful/version-descriptions
Merge into: lp:lazr.restful
Diff against target: 321 lines (+127/-28)
7 files modified
src/lazr/restful/NEWS.txt (+8/-0)
src/lazr/restful/example/base/root.py (+15/-8)
src/lazr/restful/example/base/tests/wadl.txt (+30/-14)
src/lazr/restful/example/multiversion/tests/wadl.txt (+20/-3)
src/lazr/restful/interfaces/_rest.py (+26/-1)
src/lazr/restful/tales.py (+15/-2)
src/lazr/restful/templates/wadl-root.pt (+13/-0)
To merge this branch: bzr merge lp:~leonardr/lazr.restful/version-descriptions
Reviewer Review Type Date Requested Status
Gary Poster Approve
Review via email: mp+21075@code.launchpad.net

Description of the change

This branch adds two new attributes to web service configuration, "service_description" and "version_descriptions". "service_description" is supposed to be a human-readable overview of the web service; version_descriptions is a map of version names to human-readable overviews of what makes that version different.

Both attributes are put into <doc> tags in the generated WADL. For my next trick, I'll pull them out of the WADL and incorporate them into the generated Launchpad API documentation.

To post a comment you must log in.
Revision history for this message
Gary Poster (gary) wrote :

merge-conditional

Thank you

Gary

[2:46pm] gary_poster: leonardr: "[x for x in contents['service_doc']]" -> "list(contents['service_doc']]" ?
[2:47pm] gary_poster: leonardr: lines 189 and 191 of diff
[2:47pm] leonardr: gary: sure
[2:47pm] gary_poster: cool
[2:48pm] gary_poster: leonardr: do you intend to keep pdb around? line 286
[2:48pm] leonardr: gary, no, that's in by mistake
[2:48pm] gary_poster: cool
[2:49pm] gary_poster: leonardr: otherwise, r=gary. Will mark as such.
[2:49pm] leonardr: gary: also the mssing = object() needs to go
[2:49pm] gary_poster: ah, ok. Should have investigated more carefully then.

review: Approve
126. By Leonard Richardson

Response to feedback.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/lazr/restful/NEWS.txt'
--- src/lazr/restful/NEWS.txt 2010-03-03 13:08:12 +0000
+++ src/lazr/restful/NEWS.txt 2010-03-10 20:48:29 +0000
@@ -5,6 +5,14 @@
5Development5Development
6===========6===========
77
8There are two new attributes of the web service configuratino,
9"service_description" and "version_descriptions". Both are optional,
10but they're useful for giving your users an overview of your web
11service and of the differences between versions.
12
130.9.22 (2010-03-05)
14===================
15
8Special note: this version will break backwards compatibility in your16Special note: this version will break backwards compatibility in your
9web service unless you take a special step. See17web service unless you take a special step. See
10"last_version_with_named_mutator_operations" below.18"last_version_with_named_mutator_operations" below.
1119
=== modified file 'src/lazr/restful/example/base/root.py'
--- src/lazr/restful/example/base/root.py 2010-02-25 17:07:16 +0000
+++ src/lazr/restful/example/base/root.py 2010-03-10 20:48:29 +0000
@@ -385,12 +385,19 @@
385385
386class WebServiceConfiguration(BaseWebServiceConfiguration):386class WebServiceConfiguration(BaseWebServiceConfiguration):
387 directives.publication_class(WebServiceTestPublication)387 directives.publication_class(WebServiceTestPublication)
388 code_revision='test.revision'388 code_revision = 'test.revision'
389 default_batch_size=5389 default_batch_size = 5
390 hostname='cookbooks.dev'390 hostname = 'cookbooks.dev'
391 match_batch_size=50391 match_batch_size = 50
392 active_versions=['1.0', 'devel']392 active_versions = ['1.0', 'devel']
393 last_version_with_mutator_named_operations=None393 service_description = """<p>This is a web service.</p>
394 use_https=False394 <p>It's got resources!</p>"""
395 view_permission='lazr.restful.example.base.View'395 version_descriptions = { 'devel' : """<p>The unstable development
396 version.</p>
397
398 <p>Don't use this unless you like changing things.</p>"""
399 }
400 last_version_with_mutator_named_operations = None
401 use_https = False
402 view_permission = 'lazr.restful.example.base.View'
396403
397404
=== modified file 'src/lazr/restful/example/base/tests/wadl.txt'
--- src/lazr/restful/example/base/tests/wadl.txt 2010-02-15 14:56:36 +0000
+++ src/lazr/restful/example/base/tests/wadl.txt 2010-03-10 20:48:29 +0000
@@ -6,7 +6,6 @@
6format. These documents are similar to the HTML documents that provide6format. These documents are similar to the HTML documents that provide
7human beings with links to click and forms to fill out.7human beings with links to click and forms to fill out.
88
9===============
10Entry resources9Entry resources
11===============10===============
1211
@@ -103,7 +102,6 @@
103document that says "The resource at this URL is of type [foo]," where102document that says "The resource at this URL is of type [foo]," where
104[foo] is a reference to another WADL document.103[foo] is a reference to another WADL document.
105104
106====================
107Collection resources105Collection resources
108====================106====================
109107
@@ -137,7 +135,6 @@
137 >>> resource.attrib['type']135 >>> resource.attrib['type']
138 'http://...#cookbooks'136 'http://...#cookbooks'
139137
140===========================
141Scoped collection resources138Scoped collection resources
142===========================139===========================
143140
@@ -165,7 +162,6 @@
165 >>> resource.attrib['type']162 >>> resource.attrib['type']
166 'http://...#recipe-page-resource'163 'http://...#recipe-page-resource'
167164
168=====================
169Hosted file resources165Hosted file resources
170=====================166=====================
171167
@@ -224,7 +220,6 @@
224 >>> resource.attrib['type']220 >>> resource.attrib['type']
225 'http://...#HostedFile'221 'http://...#HostedFile'
226222
227================
228The service root223The service root
229================224================
230225
@@ -257,19 +252,41 @@
257located here are the descriptions of the JSON representations those252located here are the descriptions of the JSON representations those
258resources serve.253resources serve.
259254
260======================================255Description of the full service
261Description of the service root itself256--------------------------------
262======================================257
263258The first two tags in the WADL file are human-readable documentation
264Let's whittle down the complexity a little by taking a look at the259for the entire web service.
265description of the service root resource itself.260
266261
267 >>> from lxml.etree import _Comment262 >>> from lxml.etree import _Comment
268 >>> children = [child for child in tree263 >>> children = [child for child in tree
269 ... if not isinstance(child, _Comment)]264 ... if not isinstance(child, _Comment)]
270 >>> resources, service_root_type, service_root_repr = children[:3]265
266 >>> service_doc, version_doc = children[:2]
267 >>> print service_doc.attrib['title']
268 About this service
269 >>> for p_tag in service_doc:
270 ... print p_tag.text
271 This is a web service.
272 It's got resources!
273
274 >>> print version_doc.attrib['title']
275 About version devel
276 >>> for p_tag in version_doc:
277 ... print p_tag.text
278 The unstable development version.
279 Don't use this unless you like changing things.
280
281Description of the service root itself
282--------------------------------------
283
284Let's whittle down the complexity a little more by taking a look at
285the description of the service root resource itself.
286
287 >>> resources, service_root_type, service_root_repr = children[2:5]
271 >>> # We'll deal with the rest of the children later.288 >>> # We'll deal with the rest of the children later.
272 >>> other_children = children[3:]289 >>> other_children = children[5:]
273290
274The service root is an instance of a special resource type that291The service root is an instance of a special resource type that
275responds only to GET.292responds only to GET.
@@ -397,7 +414,6 @@
397Aha! There's a resource of type "service-root" right there at the414Aha! There's a resource of type "service-root" right there at the
398service root! Who would have thought?415service root! Who would have thought?
399416
400========================
401The rest of the document417The rest of the document
402========================418========================
403419
404420
=== modified file 'src/lazr/restful/example/multiversion/tests/wadl.txt'
--- src/lazr/restful/example/multiversion/tests/wadl.txt 2010-02-11 16:36:47 +0000
+++ src/lazr/restful/example/multiversion/tests/wadl.txt 2010-03-10 20:48:29 +0000
@@ -24,9 +24,10 @@
24 ... api_version=version).body24 ... api_version=version).body
25 ... tree = etree.fromstring(wadl)25 ... tree = etree.fromstring(wadl)
26 ...26 ...
27 ... keys = ("base service_root service_root_json pair_collection "27 ... keys = ("service_doc version_doc base service_root "
28 ... "pair_entry pair_full_json pair_diff_jaon pair_page "28 ... "service_root_json pair_collection pair_entry"
29 ... "pair_page_json hosted_file hosted_file_representation"29 ... "pair_full_json pair_diff_jaon pair_page pair_page_json"
30 ... "hosted_file hosted_file_representation"
30 ... ).split()31 ... ).split()
31 ...32 ...
32 ... tags = [child for child in tree if not isinstance(child, _Comment)]33 ... tags = [child for child in tree if not isinstance(child, _Comment)]
@@ -39,6 +40,9 @@
39is not present at all.40is not present at all.
4041
41 >>> contents = wadl_contents_for_version('beta')42 >>> contents = wadl_contents_for_version('beta')
43 >>> print contents['version_doc'].attrib['title']
44 About version beta
45
42 >>> print contents['base'].attrib['base']46 >>> print contents['base'].attrib['base']
43 http://multiversion.dev/beta/47 http://multiversion.dev/beta/
4448
@@ -46,9 +50,20 @@
46 >>> sorted([method.attrib['id'] for method in pair_collection])50 >>> sorted([method.attrib['id'] for method in pair_collection])
47 ['key_value_pairs-get']51 ['key_value_pairs-get']
4852
53As a side note, see that the service documentation and version
54documentation tags are empty, because this service's configuration
55doesn't specify that information:
56
57 >>> len(list(contents['service_doc']))
58 0
59 >>> len(list(contents['version_doc']))
60 0
61
49In '2.0', the by_value method is called 'byValue'.62In '2.0', the by_value method is called 'byValue'.
5063
51 >>> contents = wadl_contents_for_version('2.0')64 >>> contents = wadl_contents_for_version('2.0')
65 >>> print contents['version_doc'].attrib['title']
66 About version 2.0
52 >>> print contents['base'].attrib['base']67 >>> print contents['base'].attrib['base']
53 http://multiversion.dev/2.0/68 http://multiversion.dev/2.0/
5469
@@ -59,6 +74,8 @@
59In '3.0', the method changes its name to 'by_value'.74In '3.0', the method changes its name to 'by_value'.
6075
61 >>> contents = wadl_contents_for_version('3.0')76 >>> contents = wadl_contents_for_version('3.0')
77 >>> print contents['version_doc'].attrib['title']
78 About version 3.0
62 >>> print contents['base'].attrib['base']79 >>> print contents['base'].attrib['base']
63 http://multiversion.dev/3.0/80 http://multiversion.dev/3.0/
6481
6582
=== modified file 'src/lazr/restful/interfaces/_rest.py'
--- src/lazr/restful/interfaces/_rest.py 2010-02-24 18:02:29 +0000
+++ src/lazr/restful/interfaces/_rest.py 2010-03-10 20:48:29 +0000
@@ -52,7 +52,7 @@
52 'IWebServiceVersion',52 'IWebServiceVersion',
53 ]53 ]
5454
55from zope.schema import Bool, Int, List, TextLine55from zope.schema import Bool, Dict, Int, List, Text, TextLine
56from zope.interface import Attribute, Interface56from zope.interface import Attribute, Interface
57# These two should really be imported from zope.interface, but57# These two should really be imported from zope.interface, but
58# the import fascist complains because they are not in __all__ there.58# the import fascist complains because they are not in __all__ there.
@@ -394,6 +394,16 @@
394 These are miscellaneous strings that may differ in different web394 These are miscellaneous strings that may differ in different web
395 services.395 services.
396 """396 """
397 service_description = TextLine(
398 title=u"Service description",
399 description=u"""A human-readable description of the web service.
400
401 The description may contain HTML, but if it does, it must be a
402 valid XHTML fragment.
403 """,
404 default=u"",
405 )
406
397 view_permission = TextLine(407 view_permission = TextLine(
398 title=u"View permission", default=u"zope.View",408 title=u"View permission", default=u"zope.View",
399 description=u"The permission to use when checking object visibility.")409 description=u"The permission to use when checking object visibility.")
@@ -448,6 +458,21 @@
448458
449 This list must contain at least one version name.""")459 This list must contain at least one version name.""")
450460
461 version_descriptions = Dict(
462 key_type = TextLine(),
463 value_type = Text(),
464 title = u"Human-readable descriptions of the web service versions.",
465 description = u"""A dictionary mapping version names to
466 human-readable descriptions. The descriptions should describe
467 what distinguishes this version from other versions, and
468 mention if/when the version will be removed.
469
470 The descriptions may contain HTML, but if they do, they must be
471 valid XHTML fragments.
472 """,
473 default = {}
474 )
475
451 last_version_with_mutator_named_operations = TextLine(476 last_version_with_mutator_named_operations = TextLine(
452 default=None,477 default=None,
453 description=u"""In earlier versions of lazr.restful, mutator methods478 description=u"""In earlier versions of lazr.restful, mutator methods
454479
=== modified file 'src/lazr/restful/tales.py'
--- src/lazr/restful/tales.py 2010-02-18 15:02:10 +0000
+++ src/lazr/restful/tales.py 2010-03-10 20:48:29 +0000
@@ -32,8 +32,8 @@
32 ICollection, ICollectionField, IEntry, IJSONRequestCache,32 ICollection, ICollectionField, IEntry, IJSONRequestCache,
33 IReferenceChoice, IResourceDELETEOperation, IResourceGETOperation,33 IReferenceChoice, IResourceDELETEOperation, IResourceGETOperation,
34 IResourceOperation, IResourcePOSTOperation, IScopedCollection,34 IResourceOperation, IResourcePOSTOperation, IScopedCollection,
35 ITopLevelEntryLink, IWebServiceClientRequest, IWebServiceVersion,35 ITopLevelEntryLink, IWebServiceClientRequest, IWebServiceConfiguration,
36 LAZR_WEBSERVICE_NAME)36 IWebServiceVersion, LAZR_WEBSERVICE_NAME)
37from lazr.restful.utils import get_current_web_service_request37from lazr.restful.utils import get_current_web_service_request
3838
3939
@@ -221,6 +221,19 @@
221 return self._service_root_url()221 return self._service_root_url()
222222
223 @property223 @property
224 def description(self):
225 return getUtility(IWebServiceConfiguration).service_description
226
227 @property
228 def service_version(self):
229 return self.resource.request.version
230
231 @property
232 def version_description(self):
233 config = getUtility(IWebServiceConfiguration)
234 return config.version_descriptions.get(self.service_version, None)
235
236 @property
224 def top_level_resources(self):237 def top_level_resources(self):
225 """Return a list of dicts describing the top-level resources."""238 """Return a list of dicts describing the top-level resources."""
226 resource_dicts = []239 resource_dicts = []
227240
=== modified file 'src/lazr/restful/templates/wadl-root.pt'
--- src/lazr/restful/templates/wadl-root.pt 2009-10-21 13:41:12 +0000
+++ src/lazr/restful/templates/wadl-root.pt 2010-03-10 20:48:29 +0000
@@ -11,6 +11,19 @@
11 xmlns:metal="http://xml.zope.org/namespaces/metal"11 xmlns:metal="http://xml.zope.org/namespaces/metal"
12>12>
1313
14 <wadl:doc xmlns="http://www.w3.org/1999/xhtml"
15 title="About this service"
16 tal:content="structure context/wadl:description">
17 Version-independent description of the web service.
18 </wadl:doc>
19
20 <wadl:doc xmlns="http://www.w3.org/1999/xhtml"
21 tal:define="version context/wadl:service_version"
22 tal:attributes="title string:About version ${version}"
23 tal:content="structure context/wadl:version_description">
24 Description of this version of the web service.
25 </wadl:doc>
26
14 <!--There is one "service root" resource, located (as you'd expect)27 <!--There is one "service root" resource, located (as you'd expect)
15 at the service root. This very document is the WADL28 at the service root. This very document is the WADL
16 representation of the "service root" resource.-->29 representation of the "service root" resource.-->

Subscribers

People subscribed via source and target branches