blob: d7852d20a3f3fefb22a9fa4723c8221bcef40ad5 [file]
from collections import namedtuple
import uuid
import marshmallow as ma
from app.objects.interfaces.i_object import FirstClassObjectInterface
from app.objects.secondclass.c_fact import FactSchema, OriginType
from app.objects.secondclass.c_rule import RuleSchema
from app.objects.secondclass.c_relationship import RelationshipSchema
from app.utility.base_object import BaseObject
class AdjustmentSchema(ma.Schema):
ability_id = ma.fields.String()
trait = ma.fields.String()
value = ma.fields.String()
offset = ma.fields.Integer()
@ma.post_load()
def build_adjustment(self, data, **_):
return Adjustment(**data)
Adjustment = namedtuple('Adjustment', 'ability_id trait value offset')
class SourceSchema(ma.Schema):
id = ma.fields.String()
name = ma.fields.String()
facts = ma.fields.List(ma.fields.Nested(FactSchema))
rules = ma.fields.List(ma.fields.Nested(RuleSchema))
adjustments = ma.fields.List(ma.fields.Nested(AdjustmentSchema))
relationships = ma.fields.List(ma.fields.Nested(RelationshipSchema))
plugin = ma.fields.String(load_default=None)
@ma.pre_load
def fix_adjustments(self, in_data, **_):
x = []
raw_adjustments = in_data.pop('adjustments', {})
if raw_adjustments and isinstance(raw_adjustments, dict):
for ability_id, adjustments in raw_adjustments.items():
for trait, block in adjustments.items():
for change in block:
x.append(dict(ability_id=ability_id, trait=trait, value=change.get('value'),
offset=change.get('offset')))
in_data['adjustments'] = x
self._fix_loaded_object_origins(in_data)
return in_data
@ma.post_load()
def build_source(self, data, **kwargs):
return None if kwargs.get('partial') is True else Source(**data)
@staticmethod
def _fix_loaded_object_origins(input_data):
"""
Sort through input_data's facts and relationships, and patch them to include origin and references
:param input_data: A 'source' dictionary
:return: input_data with updated facts/relationships (patched in place)
"""
for y in input_data.get('facts', []):
y['origin_type'] = OriginType.IMPORTED.name
y['source'] = input_data['id']
for y in input_data.get('relationships', []):
y['source']['origin_type'] = OriginType.IMPORTED.name
y['source']['source'] = input_data['id']
if y.get('target'):
y['target']['origin_type'] = OriginType.IMPORTED.name
y['target']['source'] = input_data['id']
class Source(FirstClassObjectInterface, BaseObject):
schema = SourceSchema()
display_schema = SourceSchema(exclude=('adjustments',))
@property
def unique(self):
return self.hash('%s' % self.id)
def __init__(self, name='', id='', facts=(), relationships=(), rules=(), adjustments=(), plugin=''):
super().__init__()
self.id = id if id else str(uuid.uuid4())
self.name = name
self.facts = facts
self.rules = rules
self.adjustments = adjustments
self.relationships = relationships
self.plugin = plugin
def store(self, ram):
existing = self.retrieve(ram['sources'], self.unique)
if not existing:
ram['sources'].append(self)
return self.retrieve(ram['sources'], self.unique)
existing.update('name', self.name)
existing.update('facts', self.facts)
existing.update('rules', self.rules)
existing.update('relationships', self.relationships)
existing.update('plugin', self.plugin)
return existing