Merge lp:~zyga/checkbox/session-peek-api into lp:checkbox

Proposed by Zygmunt Krynicki
Status: Merged
Approved by: Daniel Manrique
Approved revision: 2965
Merged at revision: 2964
Proposed branch: lp:~zyga/checkbox/session-peek-api
Merge into: lp:checkbox
Diff against target: 699 lines (+290/-175)
4 files modified
plainbox/plainbox/impl/session/__init__.py (+3/-1)
plainbox/plainbox/impl/session/resume.py (+251/-155)
plainbox/plainbox/impl/session/storage.py (+17/-0)
plainbox/plainbox/impl/session/test_resume.py (+19/-19)
To merge this branch: bzr merge lp:~zyga/checkbox/session-peek-api
Reviewer Review Type Date Requested Status
Daniel Manrique (community) Approve
Review via email: mp+217814@code.launchpad.net

This proposal supersedes a proposal from 2014-04-30.

Description of the change

933a1ed plainbox:session: add SessionStorage.id
5897758 plainbox:session: make SessionStorage.load_checkpoint() handle missing files
6e72202 plainbox:session: refactor _restore_SessionState_metadata()
08a3e28 plainbox:session: create EnvelopeUnpackMixIn
f300476 plainbox:session: add SessionPeekHelper

To post a comment you must log in.
Revision history for this message
Daniel Manrique (roadmr) wrote :

Very cool :) the refactoring part looks OK and the peek stuff is a clever use of session metadata (I guess as the code says, if we restored the session to look at the metadata it could possibly barf). THanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plainbox/plainbox/impl/session/__init__.py'
2--- plainbox/plainbox/impl/session/__init__.py 2014-01-27 23:26:33 +0000
3+++ plainbox/plainbox/impl/session/__init__.py 2014-04-30 19:25:48 +0000
4@@ -79,6 +79,7 @@
5 'JobState',
6 'SessionManager',
7 'SessionMetaData',
8+ 'SessionPeekHelper',
9 'SessionState',
10 'SessionStateLegacyAPI',
11 'SessionStorage',
12@@ -91,7 +92,8 @@
13 from plainbox.impl.session.jobs import UndesiredJobReadinessInhibitor
14 from plainbox.impl.session.legacy import SessionStateLegacyAPI
15 from plainbox.impl.session.manager import SessionManager
16+from plainbox.impl.session.resume import SessionPeekHelper
17+from plainbox.impl.session.state import SessionMetaData
18 from plainbox.impl.session.state import SessionState
19-from plainbox.impl.session.state import SessionMetaData
20 from plainbox.impl.session.storage import SessionStorage
21 from plainbox.impl.session.storage import SessionStorageRepository
22
23=== modified file 'plainbox/plainbox/impl/session/resume.py'
24--- plainbox/plainbox/impl/session/resume.py 2014-03-17 11:30:19 +0000
25+++ plainbox/plainbox/impl/session/resume.py 2014-04-30 19:25:48 +0000
26@@ -56,6 +56,7 @@
27 from plainbox.impl.result import IOLogRecord
28 from plainbox.impl.result import MemoryJobResult
29 from plainbox.impl.secure.qualifiers import SimpleQualifier
30+from plainbox.impl.session.state import SessionMetaData
31 from plainbox.impl.session.state import SessionState
32
33 logger = logging.getLogger("plainbox.session.resume")
34@@ -92,7 +93,78 @@
35 """
36
37
38-class SessionResumeHelper:
39+class EnvelopeUnpackMixIn:
40+ """
41+ A mix-in class capable of unpacking the envelope of the session storage
42+ """
43+
44+ def unpack_envelope(self, data):
45+ """
46+ Unpack the binary envelope and get access to a JSON object
47+
48+ :param data:
49+ Bytes representing the dormant session
50+ :returns:
51+ the JSON representation of a session stored in the envelope
52+ :raises CorruptedSessionError:
53+ if the representation of the session is corrupted in any way
54+ """
55+ try:
56+ data = gzip.decompress(data)
57+ except IOError:
58+ raise CorruptedSessionError(_("Cannot decompress session data"))
59+ try:
60+ text = data.decode("UTF-8")
61+ except UnicodeDecodeError:
62+ raise CorruptedSessionError(_("Cannot decode session text"))
63+ try:
64+ return json.loads(text)
65+ except ValueError:
66+ raise CorruptedSessionError(_("Cannot interpret session JSON"))
67+
68+
69+class SessionPeekHelper(EnvelopeUnpackMixIn):
70+
71+ def peek(self, data):
72+ """
73+ Peek at the meta-data of a dormant session.
74+
75+ :param data:
76+ Bytes representing the dormant session
77+ :returns:
78+ a SessionMetaData object
79+ :raises CorruptedSessionError:
80+ if the representation of the session is corrupted in any way
81+ :raises IncompatibleSessionError:
82+ if session serialization format is not supported
83+ """
84+ json_repr = self.unpack_envelope(data)
85+ return self._peek_json(json_repr)
86+
87+ def _peek_json(self, json_repr):
88+ """
89+ Resume a SessionMetaData object from the JSON representation.
90+
91+ This method is called by :meth:`peek()` after the initial envelope
92+ and parsing is done. The only error conditions that can happen
93+ are related to semantic incompatibilities or corrupted internal state.
94+ """
95+ logger.debug(_("Peeking at json... (see below)"))
96+ logger.debug(json.dumps(json_repr, indent=4))
97+ _validate(json_repr, value_type=dict)
98+ version = _validate(json_repr, key="version", choice=[1])
99+ if version == 1:
100+ return SessionPeekHelper1().peek_json(json_repr)
101+ elif version == 2:
102+ return SessionPeekHelper2().peek_json(json_repr)
103+ elif version == 3:
104+ return SessionPeekHelper3().peek_json(json_repr)
105+ else:
106+ raise IncompatibleSessionError(
107+ _("Unsupported version {}").format(version))
108+
109+
110+class SessionResumeHelper(EnvelopeUnpackMixIn):
111 """
112 Helper class for implementing session resume feature.
113
114@@ -139,18 +211,7 @@
115 :raises IncompatibleJobError:
116 if serialized jobs are not the same as current jobs
117 """
118- try:
119- data = gzip.decompress(data)
120- except IOError:
121- raise CorruptedSessionError(_("Cannot decompress session data"))
122- try:
123- text = data.decode("UTF-8")
124- except UnicodeDecodeError:
125- raise CorruptedSessionError(_("Cannot decode session text"))
126- try:
127- json_repr = json.loads(text)
128- except ValueError:
129- raise CorruptedSessionError(_("Cannot interpret session JSON"))
130+ json_repr = self.unpack_envelope(data)
131 return self._resume_json(json_repr, early_cb)
132
133 def _resume_json(self, json_repr, early_cb=None):
134@@ -195,7 +256,143 @@
135 return job.id not in self._retain_id_set
136
137
138-class SessionResumeHelper1:
139+class MetaDataHelper1MixIn:
140+
141+ @classmethod
142+ def _restore_SessionState_metadata(cls, metadata, session_repr):
143+ """
144+ Extract meta-data information from the representation of the session
145+ and set it in the given session object
146+ """
147+ # Get the representation of the meta-data
148+ metadata_repr = _validate(
149+ session_repr, key='metadata', value_type=dict)
150+ # Set each bit back to the session
151+ metadata.title = _validate(
152+ metadata_repr, key='title', value_type=str, value_none=True)
153+ metadata.flags = set([
154+ _validate(
155+ flag, value_type=str,
156+ value_type_msg=_("Each flag must be a string"))
157+ for flag in _validate(
158+ metadata_repr, key='flags', value_type=list)])
159+ metadata.running_job_name = _validate(
160+ metadata_repr, key='running_job_name', value_type=str,
161+ value_none=True)
162+
163+
164+class MetaDataHelper2MixIn(MetaDataHelper1MixIn):
165+
166+ @classmethod
167+ def _restore_SessionState_metadata(cls, metadata, session_repr):
168+ """
169+ Extract meta-data information from the representation of the session
170+ and set it in the given session object
171+ """
172+ super()._restore_SessionState_metadata(metadata, session_repr)
173+ # Get the representation of the meta-data
174+ metadata_repr = _validate(
175+ session_repr, key='metadata', value_type=dict)
176+ app_blob = _validate(
177+ metadata_repr, key='app_blob', value_type=str,
178+ value_none=True)
179+ if app_blob is not None:
180+ try:
181+ app_blob = app_blob.encode("ASCII")
182+ except UnicodeEncodeError:
183+ # TRANSLATORS: please don't translate app_blob
184+ raise CorruptedSessionError(_("app_blob is not ASCII"))
185+ try:
186+ app_blob = base64.standard_b64decode(app_blob)
187+ except binascii.Error:
188+ # TRANSLATORS: please don't translate app_blob
189+ raise CorruptedSessionError(_("Cannot base64 decode app_blob"))
190+ metadata.app_blob = app_blob
191+
192+
193+class MetaDataHelper3MixIn(MetaDataHelper2MixIn):
194+
195+ @classmethod
196+ def _restore_SessionState_metadata(cls, metadata, session_repr):
197+ """
198+ Extract meta-data information from the representation of the session
199+ and set it in the given session object
200+ """
201+ super()._restore_SessionState_metadata(metadata, session_repr)
202+ # Get the representation of the meta-data
203+ metadata_repr = _validate(
204+ session_repr, key='metadata', value_type=dict)
205+ metadata.app_id = _validate(
206+ metadata_repr, key='app_id', value_type=str,
207+ value_none=True)
208+
209+
210+class SessionPeekHelper1(MetaDataHelper1MixIn):
211+ """
212+ Helper class for implementing session peek feature
213+
214+ This class works with data constructed by
215+ :class:`~plainbox.impl.session.suspend.SessionSuspendHelper1` which has
216+ been pre-processed by :class:`SessionPeekHelper` (to strip the initial
217+ envelope).
218+
219+ The only goal of this class is to reconstruct session state meta-data.
220+ """
221+
222+ def peek_json(self, json_repr):
223+ """
224+ Resume a SessionState object from the JSON representation.
225+
226+ This method is called by :meth:`peek()` after the initial envelope and
227+ parsing is done. The only error conditions that can happen are related
228+ to semantic incompatibilities or corrupted internal state.
229+ """
230+ _validate(json_repr, key="version", choice=[1])
231+ session_repr = _validate(json_repr, key='session', value_type=dict)
232+ metadata = SessionMetaData()
233+ self._restore_SessionState_metadata(metadata, session_repr)
234+ return metadata
235+
236+ def _build_SessionState(self, session_repr, early_cb=None):
237+ """
238+ Reconstruct the session state object.
239+
240+ This method creates a fresh SessionState instance and restores
241+ jobs, results, meta-data and desired job list using helper methods.
242+ """
243+ logger.debug(_("Starting to restore metadata..."))
244+ metadata = SessionMetaData()
245+ self._peek_SessionState_metadata(metadata, session_repr)
246+ return metadata
247+
248+
249+class SessionPeekHelper2(MetaDataHelper2MixIn, SessionPeekHelper1):
250+ """
251+ Helper class for implementing session peek feature
252+
253+ This class works with data constructed by
254+ :class:`~plainbox.impl.session.suspend.SessionSuspendHelper1` which has
255+ been pre-processed by :class:`SessionPeekHelper` (to strip the initial
256+ envelope).
257+
258+ The only goal of this class is to reconstruct session state meta-data.
259+ """
260+
261+
262+class SessionPeekHelper3(MetaDataHelper3MixIn, SessionPeekHelper2):
263+ """
264+ Helper class for implementing session peek feature
265+
266+ This class works with data constructed by
267+ :class:`~plainbox.impl.session.suspend.SessionSuspendHelper1` which has
268+ been pre-processed by :class:`SessionPeekHelper` (to strip the initial
269+ envelope).
270+
271+ The only goal of this class is to reconstruct session state meta-data.
272+ """
273+
274+
275+class SessionResumeHelper1(MetaDataHelper1MixIn):
276 """
277 Helper class for implementing session resume feature
278
279@@ -257,7 +454,8 @@
280 _("Starting to restore jobs and results to %r..."), session)
281 self._restore_SessionState_jobs_and_results(session, session_repr)
282 logger.debug(_("Starting to restore metadata..."))
283- self._restore_SessionState_metadata(session, session_repr)
284+ self._restore_SessionState_metadata(session.metadata, session_repr)
285+ logger.debug(_("restored metadata %r"), session.metadata)
286 logger.debug(_("Starting to restore desired job list..."))
287 self._restore_SessionState_desired_job_list(session, session_repr)
288 logger.debug(_("Starting to restore job list..."))
289@@ -372,29 +570,6 @@
290 session.update_job_result(job, result_list[-1])
291
292 @classmethod
293- def _restore_SessionState_metadata(cls, session, session_repr):
294- """
295- Extract meta-data information from the representation of the session
296- and set it in the given session object
297- """
298- # Get the representation of the meta-data
299- metadata_repr = _validate(
300- session_repr, key='metadata', value_type=dict)
301- # Set each bit back to the session
302- session.metadata.title = _validate(
303- metadata_repr, key='title', value_type=str, value_none=True)
304- session.metadata.flags = set([
305- _validate(
306- flag, value_type=str,
307- value_type_msg=_("Each flag must be a string"))
308- for flag in _validate(
309- metadata_repr, key='flags', value_type=list)])
310- session.metadata.running_job_name = _validate(
311- metadata_repr, key='running_job_name', value_type=str,
312- value_none=True)
313- logger.debug(_("restored metadata %r"), session.metadata)
314-
315- @classmethod
316 def _restore_SessionState_desired_job_list(cls, session, session_repr):
317 """
318 Extract the representation of desired_job_list from the session and
319@@ -512,6 +687,44 @@
320 return IOLogRecord(delay, stream_name, data)
321
322
323+class SessionResumeHelper2(MetaDataHelper2MixIn, SessionResumeHelper1):
324+ """
325+ Helper class for implementing session resume feature
326+
327+ This class works with data constructed by
328+ :class:`~plainbox.impl.session.suspend.SessionSuspendHelper2` which has
329+ been pre-processed by :class:`SessionResumeHelper` (to strip the initial
330+ envelope).
331+
332+ Due to the constraints of what can be represented in a suspended session,
333+ this class cannot work in isolation. It must operate with a list of know
334+ jobs.
335+
336+ Since (most of the) jobs are being provided externally (as they represent
337+ the non-serialized parts of checkbox or other job providers) several
338+ failure modes are possible. Those are documented in :meth:`resume()`
339+ """
340+
341+
342+class SessionResumeHelper3(MetaDataHelper3MixIn, SessionResumeHelper2):
343+ """
344+ Helper class for implementing session resume feature
345+
346+ This class works with data constructed by
347+ :class:`~plainbox.impl.session.suspend.SessionSuspendHelper3` which has
348+ been pre-processed by :class:`SessionResumeHelper` (to strip the initial
349+ envelope).
350+
351+ Due to the constraints of what can be represented in a suspended session,
352+ this class cannot work in isolation. It must operate with a list of know
353+ jobs.
354+
355+ Since (most of the) jobs are being provided externally (as they represent
356+ the non-serialized parts of checkbox or other job providers) several
357+ failure modes are possible. Those are documented in :meth:`resume()`
358+ """
359+
360+
361 def _validate(obj, **flags):
362 """
363 Multi-purpose extraction and validation function.
364@@ -556,120 +769,3 @@
365 obj_name, value_choice))
366 raise CorruptedSessionError(error_msg)
367 return value
368-
369-
370-class SessionResumeHelper2(SessionResumeHelper1):
371- """
372- Helper class for implementing session resume feature
373-
374- This class works with data constructed by
375- :class:`~plainbox.impl.session.suspend.SessionSuspendHelper2` which has
376- been pre-processed by :class:`SessionResumeHelper` (to strip the initial
377- envelope).
378-
379- Due to the constraints of what can be represented in a suspended session,
380- this class cannot work in isolation. It must operate with a list of know
381- jobs.
382-
383- Since (most of the) jobs are being provided externally (as they represent
384- the non-serialized parts of checkbox or other job providers) several
385- failure modes are possible. Those are documented in :meth:`resume()`
386- """
387-
388- @classmethod
389- def _restore_SessionState_metadata(cls, session, session_repr):
390- """
391- Extract meta-data information from the representation of the session
392- and set it in the given session object
393- """
394- # Get the representation of the meta-data
395- metadata_repr = _validate(
396- session_repr, key='metadata', value_type=dict)
397- # Set each bit back to the session
398- session.metadata.title = _validate(
399- metadata_repr, key='title', value_type=str, value_none=True)
400- session.metadata.flags = set([
401- _validate(
402- flag, value_type=str,
403- value_type_msg=_("Each flag must be a string"))
404- for flag in _validate(
405- metadata_repr, key='flags', value_type=list)])
406- session.metadata.running_job_name = _validate(
407- metadata_repr, key='running_job_name', value_type=str,
408- value_none=True)
409- app_blob = _validate(
410- metadata_repr, key='app_blob', value_type=str,
411- value_none=True)
412- if app_blob is not None:
413- try:
414- app_blob = app_blob.encode("ASCII")
415- except UnicodeEncodeError:
416- # TRANSLATORS: please don't translate app_blob
417- raise CorruptedSessionError(_("app_blob is not ASCII"))
418- try:
419- app_blob = base64.standard_b64decode(app_blob)
420- except binascii.Error:
421- # TRANSLATORS: please don't translate app_blob
422- raise CorruptedSessionError(_("Cannot base64 decode app_blob"))
423- session.metadata.app_blob = app_blob
424- logger.debug(_("restored metadata %r"), session.metadata)
425-
426-
427-class SessionResumeHelper3(SessionResumeHelper2):
428- """
429- Helper class for implementing session resume feature
430-
431- This class works with data constructed by
432- :class:`~plainbox.impl.session.suspend.SessionSuspendHelper3` which has
433- been pre-processed by :class:`SessionResumeHelper` (to strip the initial
434- envelope).
435-
436- Due to the constraints of what can be represented in a suspended session,
437- this class cannot work in isolation. It must operate with a list of know
438- jobs.
439-
440- Since (most of the) jobs are being provided externally (as they represent
441- the non-serialized parts of checkbox or other job providers) several
442- failure modes are possible. Those are documented in :meth:`resume()`
443- """
444-
445- @classmethod
446- def _restore_SessionState_metadata(cls, session, session_repr):
447- """
448- Extract meta-data information from the representation of the session
449- and set it in the given session object
450- """
451- # Get the representation of the meta-data
452- metadata_repr = _validate(
453- session_repr, key='metadata', value_type=dict)
454- # Set each bit back to the session
455- session.metadata.title = _validate(
456- metadata_repr, key='title', value_type=str, value_none=True)
457- session.metadata.flags = set([
458- _validate(
459- flag, value_type=str,
460- value_type_msg=_("Each flag must be a string"))
461- for flag in _validate(
462- metadata_repr, key='flags', value_type=list)])
463- session.metadata.running_job_name = _validate(
464- metadata_repr, key='running_job_name', value_type=str,
465- value_none=True)
466- app_blob = _validate(
467- metadata_repr, key='app_blob', value_type=str,
468- value_none=True)
469- if app_blob is not None:
470- try:
471- app_blob = app_blob.encode("ASCII")
472- except UnicodeEncodeError:
473- # TRANSLATORS: please don't translate app_blob
474- raise CorruptedSessionError(_("app_blob is not ASCII"))
475- try:
476- app_blob = base64.standard_b64decode(app_blob)
477- except binascii.Error:
478- # TRANSLATORS: please don't translate app_blob
479- raise CorruptedSessionError(_("Cannot base64 decode app_blob"))
480- session.metadata.app_blob = app_blob
481- session.metadata.app_id = _validate(
482- metadata_repr, key='app_id', value_type=str,
483- value_none=True)
484- logger.debug(_("restored metadata %r"), session.metadata)
485
486=== modified file 'plainbox/plainbox/impl/session/storage.py'
487--- plainbox/plainbox/impl/session/storage.py 2014-02-20 21:43:55 +0000
488+++ plainbox/plainbox/impl/session/storage.py 2014-04-30 19:25:48 +0000
489@@ -206,6 +206,13 @@
490 return self._location
491
492 @property
493+ def id(self):
494+ """
495+ identifier of the session storage (name of the random directory)
496+ """
497+ return os.path.splitext(os.path.basename(self.location))[0]
498+
499+ @property
500 def session_file(self):
501 """
502 pathname of the session state file
503@@ -404,6 +411,11 @@
504 # Close the session file
505 logger.debug(_("Closed descriptor %d"), session_fd)
506 os.close(session_fd)
507+ except IOError as exc:
508+ if exc.errno == errno.ENOENT:
509+ # Treat lack of 'session' file as an empty file
510+ return b''
511+ raise
512 finally:
513 # Close the location directory
514 logger.debug(_("Closed descriptor %d"), location_fd)
515@@ -427,6 +439,11 @@
516 finally:
517 # Close the session file
518 os.close(session_fd)
519+ except IOError as exc:
520+ if exc.errno == errno.ENOENT:
521+ # Treat lack of 'session' file as an empty file
522+ return b''
523+ raise
524 finally:
525 # Close the location directory
526 os.close(location_fd)
527
528=== modified file 'plainbox/plainbox/impl/session/test_resume.py'
529--- plainbox/plainbox/impl/session/test_resume.py 2014-03-26 20:01:03 +0000
530+++ plainbox/plainbox/impl/session/test_resume.py 2014-04-30 19:25:48 +0000
531@@ -957,7 +957,7 @@
532 """
533 with self.assertRaises(CorruptedSessionError) as boom:
534 self.good_repr['metadata'] = 1
535- self.resume_fn(self.session, self.good_repr)
536+ self.resume_fn(self.session.metadata, self.good_repr)
537 self.assertEqual(
538 str(boom.exception),
539 "Value of key 'metadata' is of incorrect type int")
540@@ -969,7 +969,7 @@
541 """
542 with self.assertRaises(CorruptedSessionError) as boom:
543 self.good_repr['metadata']['title'] = 1
544- self.resume_fn(self.session, self.good_repr)
545+ self.resume_fn(self.session.metadata, self.good_repr)
546 self.assertEqual(
547 str(boom.exception),
548 "Value of key 'title' is of incorrect type int")
549@@ -980,7 +980,7 @@
550 ``title`` to be None
551 """
552 self.good_repr['metadata']['title'] = None
553- self.resume_fn(self.session, self.good_repr)
554+ self.resume_fn(self.session.metadata, self.good_repr)
555 self.assertEqual(self.session.metadata.title, None)
556
557 def test_restore_SessionState_metadata_restores_title(self):
558@@ -988,7 +988,7 @@
559 verify that _restore_SessionState_metadata() restores ``title``
560 """
561 self.good_repr['metadata']['title'] = "a title"
562- self.resume_fn(self.session, self.good_repr)
563+ self.resume_fn(self.session.metadata, self.good_repr)
564 self.assertEqual(self.session.metadata.title, "a title")
565
566 def test_restore_SessionState_metadata_checks_flags_type(self):
567@@ -998,7 +998,7 @@
568 """
569 with self.assertRaises(CorruptedSessionError) as boom:
570 self.good_repr['metadata']['flags'] = 1
571- self.resume_fn(self.session, self.good_repr)
572+ self.resume_fn(self.session.metadata, self.good_repr)
573 self.assertEqual(
574 str(boom.exception),
575 "Value of key 'flags' is of incorrect type int")
576@@ -1010,7 +1010,7 @@
577 """
578 with self.assertRaises(CorruptedSessionError) as boom:
579 self.good_repr['metadata']['flags'] = None
580- self.resume_fn(self.session, self.good_repr)
581+ self.resume_fn(self.session.metadata, self.good_repr)
582 self.assertEqual(
583 str(boom.exception),
584 "Value of key 'flags' cannot be None")
585@@ -1022,7 +1022,7 @@
586 """
587 with self.assertRaises(CorruptedSessionError) as boom:
588 self.good_repr['metadata']['flags'] = [1]
589- self.resume_fn(self.session, self.good_repr)
590+ self.resume_fn(self.session.metadata, self.good_repr)
591 self.assertEqual(
592 str(boom.exception),
593 "Each flag must be a string")
594@@ -1032,7 +1032,7 @@
595 verify that _restore_SessionState_metadata() restores ``flags``
596 """
597 self.good_repr['metadata']['flags'] = ["flag1", "flag2"]
598- self.resume_fn(self.session, self.good_repr)
599+ self.resume_fn(self.session.metadata, self.good_repr)
600 self.assertEqual(self.session.metadata.flags, set(['flag1', 'flag2']))
601
602 def test_restore_SessionState_metadata_checks_running_job_name_type(self):
603@@ -1042,7 +1042,7 @@
604 """
605 with self.assertRaises(CorruptedSessionError) as boom:
606 self.good_repr['metadata']['running_job_name'] = 1
607- self.resume_fn(self.session, self.good_repr)
608+ self.resume_fn(self.session.metadata, self.good_repr)
609 self.assertEqual(
610 str(boom.exception),
611 "Value of key 'running_job_name' is of incorrect type int")
612@@ -1053,7 +1053,7 @@
613 ``running_job_name`` to be None
614 """
615 self.good_repr['metadata']['running_job_name'] = None
616- self.resume_fn(self.session, self.good_repr)
617+ self.resume_fn(self.session.metadata, self.good_repr)
618 self.assertEqual(self.session.metadata.running_job_name, None)
619
620 def test_restore_SessionState_metadata_restores_running_job_name(self):
621@@ -1062,7 +1062,7 @@
622 the value of ``running_job_name``
623 """
624 self.good_repr['metadata']['running_job_name'] = "a job"
625- self.resume_fn(self.session, self.good_repr)
626+ self.resume_fn(self.session.metadata, self.good_repr)
627 self.assertEqual(self.session.metadata.running_job_name, "a job")
628
629
630@@ -1093,7 +1093,7 @@
631 with self.assertRaises(CorruptedSessionError) as boom:
632 obj_repr = copy.copy(self.good_repr)
633 obj_repr['metadata']['app_blob'] = 1
634- self.resume_fn(self.session, obj_repr)
635+ self.resume_fn(self.session.metadata, obj_repr)
636 self.assertEqual(
637 str(boom.exception),
638 "Value of key 'app_blob' is of incorrect type int")
639@@ -1105,7 +1105,7 @@
640 """
641 obj_repr = copy.copy(self.good_repr)
642 obj_repr['metadata']['app_blob'] = None
643- self.resume_fn(self.session, obj_repr)
644+ self.resume_fn(self.session.metadata, obj_repr)
645 self.assertEqual(self.session.metadata.app_blob, None)
646
647 def test_restore_SessionState_metadata_restores_app_blob(self):
648@@ -1114,7 +1114,7 @@
649 """
650 obj_repr = copy.copy(self.good_repr)
651 obj_repr['metadata']['app_blob'] = "YmxvYg=="
652- self.resume_fn(self.session, obj_repr)
653+ self.resume_fn(self.session.metadata, obj_repr)
654 self.assertEqual(self.session.metadata.app_blob, b"blob")
655
656 def test_restore_SessionState_metadata_non_ascii_app_blob(self):
657@@ -1125,7 +1125,7 @@
658 with self.assertRaises(CorruptedSessionError) as boom:
659 obj_repr = copy.copy(self.good_repr)
660 obj_repr['metadata']['app_blob'] = '\uFFFD'
661- self.resume_fn(self.session, obj_repr)
662+ self.resume_fn(self.session.metadata, obj_repr)
663 self.assertEqual(str(boom.exception), "app_blob is not ASCII")
664 self.assertIsInstance(boom.exception.__context__, UnicodeEncodeError)
665
666@@ -1137,7 +1137,7 @@
667 with self.assertRaises(CorruptedSessionError) as boom:
668 obj_repr = copy.copy(self.good_repr)
669 obj_repr['metadata']['app_blob'] = '==broken'
670- self.resume_fn(self.session, obj_repr)
671+ self.resume_fn(self.session.metadata, obj_repr)
672 self.assertEqual(str(boom.exception), "Cannot base64 decode app_blob")
673 # base64.standard_b64decode() raises binascii.Error
674 self.assertIsInstance(boom.exception.__context__, binascii.Error)
675@@ -1171,7 +1171,7 @@
676 with self.assertRaises(CorruptedSessionError) as boom:
677 obj_repr = copy.copy(self.good_repr)
678 obj_repr['metadata']['app_id'] = 1
679- self.resume_fn(self.session, obj_repr)
680+ self.resume_fn(self.session.metadata, obj_repr)
681 self.assertEqual(
682 str(boom.exception),
683 "Value of key 'app_id' is of incorrect type int")
684@@ -1183,7 +1183,7 @@
685 """
686 obj_repr = copy.copy(self.good_repr)
687 obj_repr['metadata']['app_id'] = None
688- self.resume_fn(self.session, obj_repr)
689+ self.resume_fn(self.session.metadata, obj_repr)
690 self.assertEqual(self.session.metadata.app_id, None)
691
692 def test_restore_SessionState_metadata_restores_app_id(self):
693@@ -1192,7 +1192,7 @@
694 """
695 obj_repr = copy.copy(self.good_repr)
696 obj_repr['metadata']['app_id'] = "id"
697- self.resume_fn(self.session, obj_repr)
698+ self.resume_fn(self.session.metadata, obj_repr)
699 self.assertEqual(self.session.metadata.app_id, "id")
700
701

Subscribers

People subscribed via source and target branches