#=========================================================================================
# Licence, Reference and Credits
#=========================================================================================
__copyright__ = "Copyright (C) CCPN project (http://www.ccpn.ac.uk) 2014 - 2022"
__credits__ = ("Ed Brooksbank, Joanna Fox, Victoria A Higman, Luca Mureddu, Eliza Płoskoń",
"Timothy J Ragan, Brian O Smith, Gary S Thompson & Geerten W Vuister")
__licence__ = ("CCPN licence. See http://www.ccpn.ac.uk/v3-software/downloads/license",
)
__reference__ = ("Skinner, S.P., Fogh, R.H., Boucher, W., Ragan, T.J., Mureddu, L.G., & Vuister, G.W.",
"CcpNmr AnalysisAssign: a flexible platform for integrated NMR analysis",
"J.Biomol.Nmr (2016), 66, 111-124, http://doi.org/10.1007/s10858-016-0060-y"
)
#=========================================================================================
# Last code modification
#=========================================================================================
__modifiedBy__ = "$modifiedBy: Ed Brooksbank $"
__dateModified__ = "$dateModified: 2022-01-21 11:22:12 +0000 (Fri, January 21, 2022) $"
__version__ = "$Revision: 3.0.4 $"
#=========================================================================================
# Created
#=========================================================================================
__author__ = "$Author: geertenv $"
__date__ = "$Date: 2018-05-14 10:28:41 +0000 (Fri, April 07, 2017) $"
#=========================================================================================
# Start of code
#=========================================================================================
[docs]class TraitJsonHandlerBase():
"""Base class for all Trait json handlers;
Any jsonHandler class must derive from TraitJsonHandlerBase and can subclass
two methods:
encode(obj, trait) which returns a json serialisable object
decode(obj, trait, value) which uses value to generate and set the new (or modified) obj
Example:
class myHandler(TraitJsonHandlerBase):
def encode(self, obj, trait):
"returns a json serialisable object"
value = getattr(obj, trait)
-- some action on value --
return value
def decode(self, obj, trait, value):
"uses value to generate and set the new (or modified) obj"
newValue = --- some action using value ---
setattr(obj, trait, newValue)
"""
[docs] def encode(self, obj, trait):
"returns a json serialisable object"
return getattr(obj, trait)
[docs] def decode(self, obj, trait, value):
"uses value to generate and set the new (or modified) obj"
setattr(obj, trait, value)
[docs]class RecursiveDictHandlerABC(TraitJsonHandlerBase):
"""Abstract base class to handle (optionally) recursion of dict-like traits
Each value of the (key,value) pairs must of CcpNmrJson (sub-)type
"""
#--------------------------------------------------------------------------------------------
# to be subclassed
#--------------------------------------------------------------------------------------------
klass = None
recursion = True
#--------------------------------------------------------------------------------------------
# end to be subclassed
#--------------------------------------------------------------------------------------------
[docs] def encode(self, obj, trait):
# convert dict into list of (key, value) pairs, recursing
# for each value of (sub-)type CcpNmrJson
# local imports to avoid circular dependencies
from ccpn.util.traits.CcpNmrJson import CcpNmrJson
theDict = getattr(obj, trait)
if not isinstance(theDict, self.klass):
raise RuntimeError('trait: "%s", expected instance class "%s", got "%s"' %
(trait, type(self.klass), type(theDict))
)
theList = []
for key, value in theDict.items():
if self.recursion and isinstance(value, CcpNmrJson):
value = value._encode()
theList.append((key, value))
return theList
[docs] def decode(self, obj, trait, theList):
# needs conversion from list into klass; recursing for each (key, value) pair
# converting this to the relevant object
# local imports to avoid circular dependencies
from ccpn.util.traits.CcpNmrJson import CcpNmrJson
result = []
for key, value in theList:
# check if this encoded a CcpNmrJson type object
if self.recursion and CcpNmrJson._isEncodedObject(value):
theDict = dict(value)
value = CcpNmrJson._newObjectFromDict(theDict)
result.append((key, value))
# convert to class
theDict = self.klass(result)
setattr(obj, trait, theDict)
# end class
[docs]class RecursiveListHandlerABC(TraitJsonHandlerBase):
"""Abstract base class to handle recursion of list-like traits
Each value of the (list must of CcpNmrJson (sub-)type
"""
#--------------------------------------------------------------------------------------------
# to be subclassed
#--------------------------------------------------------------------------------------------
klass = None
recursion = True
#--------------------------------------------------------------------------------------------
# end to be subclassed
#--------------------------------------------------------------------------------------------
[docs] def encode(self, obj, trait):
# convert list, recursing for each item of (sub-)type CcpNmrJson
# local imports to avoid circular dependencies
from ccpn.util.traits.CcpNmrJson import CcpNmrJson
theList = getattr(obj, trait)
if not isinstance(theList, self.klass):
raise RuntimeError('trait: "%s", expected instance class "%s", got "%s"' %
(trait, type(self.klass), type(theList))
)
result = []
for i, item in enumerate(theList):
if self.recursion and isinstance(item, CcpNmrJson):
item = item._encode()
result.append(item)
return result
[docs] def decode(self, obj, trait, theList):
# needs recursing for each item in theList
# converting this to the relevant klass
# local imports to avoid circular dependencies
from ccpn.util.traits.CcpNmrJson import CcpNmrJson
result = []
for item in theList:
# check if this encoded a CcpNmrJson type object
if self.recursion and CcpNmrJson._isEncodedObject(item):
theDict = dict(item)
item = CcpNmrJson._newObjectFromDict(theDict)
result.append(item)
# convert to klass
result = self.klass(result)
setattr(obj, trait, result)
# end class
[docs]class CcpNmrJsonClassHandlerABC(TraitJsonHandlerBase):
"""Abstract base class to handle class-like traits of the CcpNmrJson (sub-)type
"""
# #--------------------------------------------------------------------------------------------
# # to be subclassed
# #--------------------------------------------------------------------------------------------
# klass = None
# #--------------------------------------------------------------------------------------------
# # end to be subclassed
# #--------------------------------------------------------------------------------------------
[docs] def encode(self, obj, trait):
# convert klass, of (sub-)type CcpNmrJson
# local imports to avoid circular dependencies
from ccpn.util.traits.CcpNmrJson import CcpNmrJson
value = getattr(obj, trait)
# if not isinstance(value, self.klass):
# raise RuntimeError('trait: "%s", expected instance class "%s", got "%s"' %
# (trait, type(self.klass), type(value))
# )
if isinstance(value, CcpNmrJson):
value = value._encode()
return value
[docs] def decode(self, obj, trait, value):
# converting value to the relevant klass instance
# local imports to avoid circular dependencies
from ccpn.util.traits.CcpNmrJson import CcpNmrJson
result = value
# check if this encoded a CcpNmrJson type object
if CcpNmrJson._isEncodedObject(value):
theDict = dict(value)
result = CcpNmrJson._newObjectFromDict(theDict)
obj.setTraitValue(trait, result, force=True)