Merge lp:~cjwatson/lazr.restful/json-publishable-date into lp:lazr.restful

Proposed by Colin Watson
Status: Merged
Merged at revision: 300
Proposed branch: lp:~cjwatson/lazr.restful/json-publishable-date
Merge into: lp:lazr.restful
Diff against target: 136 lines (+45/-2)
4 files modified
NEWS.rst (+2/-0)
src/lazr/restful/_resource.py (+16/-1)
src/lazr/restful/configure.zcml (+1/-0)
src/lazr/restful/tests/test_etag.py (+26/-1)
To merge this branch: bzr merge lp:~cjwatson/lazr.restful/json-publishable-date
Reviewer Review Type Date Requested Status
Thiago F. Pappacena (community) Approve
Review via email: mp+403064@code.launchpad.net

Commit message

Fix encoding of date(time) fields for ETags.

To post a comment you must log in.
Revision history for this message
Thiago F. Pappacena (pappacena) wrote :

LGTM

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'NEWS.rst'
--- NEWS.rst 2021-05-18 16:49:19 +0000
+++ NEWS.rst 2021-05-20 14:25:47 +0000
@@ -15,6 +15,8 @@
15Stabilize ETags of entries containing collections of strings between Python15Stabilize ETags of entries containing collections of strings between Python
162 and 3 (bug 1928474).162 and 3 (bug 1928474).
1717
18Add an ``IJSONPublishable`` adapter for ``date`` and ``datetime``.
19
181.0.2 (2021-05-14)201.0.2 (2021-05-14)
19==================21==================
2022
2123
=== modified file 'src/lazr/restful/_resource.py'
--- src/lazr/restful/_resource.py 2021-05-18 16:49:19 +0000
+++ src/lazr/restful/_resource.py 2021-05-20 14:25:47 +0000
@@ -17,6 +17,7 @@
17 'EntryHTMLView',17 'EntryHTMLView',
18 'EntryResource',18 'EntryResource',
19 'HTTPResource',19 'HTTPResource',
20 'JSONDate',
20 'JSONItem',21 'JSONItem',
21 'ReadOnlyResource',22 'ReadOnlyResource',
22 'RedirectResource',23 'RedirectResource',
@@ -71,6 +72,7 @@
71 providedBy,72 providedBy,
72 Interface,73 Interface,
73 )74 )
75from zope.interface.common.idatetime import IDate
74from zope.interface.common.sequence import IFiniteSequence76from zope.interface.common.sequence import IFiniteSequence
75from zope.interface.interfaces import (77from zope.interface.interfaces import (
76 ComponentLookupError,78 ComponentLookupError,
@@ -160,7 +162,7 @@
160 elif isinstance(value, bytes):162 elif isinstance(value, bytes):
161 return value.decode("utf-8")163 return value.decode("utf-8")
162 else:164 else:
163 return simplejson.dumps(value)165 return simplejson.dumps(value, cls=ResourceJSONEncoder)
164166
165167
166def _default_html_renderer(value):168def _default_html_renderer(value):
@@ -242,6 +244,19 @@
242 return str(self.context.title)244 return str(self.context.title)
243245
244246
247@implementer(IJSONPublishable)
248@adapter(IDate)
249class JSONDate:
250 """JSONPublishable adapter for date/datetime."""
251
252 def __init__(self, context):
253 self.context = context
254
255 def toDataForJSON(self, media_type):
256 """See `IJSONPublishable`."""
257 return self.context.isoformat()
258
259
245@implementer(IHTTPResource)260@implementer(IHTTPResource)
246class RedirectResource(URLDereferencingMixin):261class RedirectResource(URLDereferencingMixin):
247 """A resource that redirects to another URL."""262 """A resource that redirects to another URL."""
248263
=== modified file 'src/lazr/restful/configure.zcml'
--- src/lazr/restful/configure.zcml 2012-03-13 02:03:47 +0000
+++ src/lazr/restful/configure.zcml 2021-05-20 14:25:47 +0000
@@ -136,6 +136,7 @@
136 <adapter factory="lazr.restful.ScopedCollection" />136 <adapter factory="lazr.restful.ScopedCollection" />
137137
138 <adapter factory="lazr.restful.JSONItem" />138 <adapter factory="lazr.restful.JSONItem" />
139 <adapter factory="lazr.restful.JSONDate" />
139140
140 <!-- Adapter for URL generation -->141 <!-- Adapter for URL generation -->
141 <adapter142 <adapter
142143
=== modified file 'src/lazr/restful/tests/test_etag.py'
--- src/lazr/restful/tests/test_etag.py 2021-05-18 16:49:19 +0000
+++ src/lazr/restful/tests/test_etag.py 2021-05-20 14:25:47 +0000
@@ -6,8 +6,16 @@
6__metaclass__ = type6__metaclass__ = type
77
8from collections import OrderedDict8from collections import OrderedDict
9from datetime import (
10 date,
11 datetime,
12 )
13import os.path
9import unittest14import unittest
1015
16from pkg_resources import resource_filename
17import pytz
18from van.testing.layer import zcml_layer
11from zope.component import provideUtility19from zope.component import provideUtility
1220
13from lazr.restful.interfaces import IWebServiceConfiguration21from lazr.restful.interfaces import IWebServiceConfiguration
@@ -21,12 +29,22 @@
21 )29 )
2230
2331
32class FunctionalLayer:
33 allow_teardown = False
34 zcml = os.path.abspath(resource_filename('lazr.restful', 'ftesting.zcml'))
35
36
37zcml_layer(FunctionalLayer)
38
39
24class TestEntryResourceETags(unittest.TestCase):40class TestEntryResourceETags(unittest.TestCase):
25 # The EntryResource uses the field values that can be written or might41 # The EntryResource uses the field values that can be written or might
26 # othwerise change as the basis for its ETags. The make_entry_etag_cores42 # othwerise change as the basis for its ETags. The make_entry_etag_cores
27 # function is passed the data about the fields and returns the read and43 # function is passed the data about the fields and returns the read and
28 # write cores.44 # write cores.
2945
46 layer = FunctionalLayer
47
30 def test_no_field_details(self):48 def test_no_field_details(self):
31 # If make_entry_etag_cores is given no field details (because no49 # If make_entry_etag_cores is given no field details (because no
32 # fields exist), the resulting cores empty strings.50 # fields exist), the resulting cores empty strings.
@@ -91,10 +109,17 @@
91 ('dict_field',109 ('dict_field',
92 {'writable': False,110 {'writable': False,
93 'value': OrderedDict((('first', 'one'), ('second', 'two')))}),111 'value': OrderedDict((('first', 'one'), ('second', 'two')))}),
112 ('date_field',
113 {'writable': False,
114 'value': date(2009, 7, 7)}),
115 ('datetime_field',
116 {'writable': False,
117 'value': datetime(2009, 7, 7, 13, 45, 0, tzinfo=pytz.utc)}),
94 ]118 ]
95 self.assertEqual(119 self.assertEqual(
96 make_entry_etag_cores(field_details),120 make_entry_etag_cores(field_details),
97 [b'["first", "second"]\0{"first": "one", "second": "two"}', b''])121 [b'["first", "second"]\x00{"first": "one", "second": "two"}\x00'
122 b'"2009-07-07"\x00"2009-07-07T13:45:00+00:00"', b''])
98123
99124
100class TestHTTPResourceETags(unittest.TestCase):125class TestHTTPResourceETags(unittest.TestCase):

Subscribers

People subscribed via source and target branches