class BaseService(object): """Base class for business layer's services objects.""" def __init__(self): self.client = RestClient(self.ENDPOINT) self._relationship = objects.get_singular(url.RELATIONSHIPS) self._object_owner = objects.get_singular(url.OBJECT_OWNERS) self._count = templates.COUNT def create_list_objs(self, factory, count, **kwargs): """Create list of objects used entity factory and REST API data (raw responses after REST API objects creation converted to list of dicts {"attr": "value", ...}). Return list of created objects. """ list_factory_objs = [factory.create() for _ in xrange(count)] list_attrs = [ self.get_obj_attrs( self.client.create_object(type=factory_obj.type, title=factory_obj.title, slug=factory_obj.code, **kwargs)) for factory_obj in list_factory_objs ] return [ self.set_obj_attrs(attrs, factory_obj, **kwargs) for attrs, factory_obj in zip(list_attrs, list_factory_objs) ] @staticmethod def get_obj_attrs(response): """Form dictionary of object's attributes (dict's items) from server response. """ def get_items_from_obj_el(obj_el): """Get values from dict object element (obj_el) and create new dict of items. """ return { "id": obj_el.get("id"), "href": obj_el.get("selfLink"), "type": obj_el.get("type"), "title": obj_el.get("title"), "code": obj_el.get("slug"), "url": environment.APP_URL + obj_el.get("viewLink")[1:], "name": re.search(r"\/([a-z_]*)\/", obj_el.get("viewLink")).group(1), "last_update": obj_el.get("updated_at") } resp = json.loads(response.text) if isinstance(resp, list) and len(resp[0]) == 2: return get_items_from_obj_el(resp[0][1].itervalues().next()) elif isinstance(resp, dict) and len(resp) == 1: return get_items_from_obj_el(resp.itervalues().next()) else: pass @staticmethod def set_obj_attrs(attrs, obj, **kwargs): # flake8: noqa """Update object's attributes according type of object and list of dicts with object's attributes (dict's items). """ if attrs.get("id"): obj.id = attrs["id"] if attrs.get("href"): obj.href = attrs["href"] if attrs.get("url"): obj.url = attrs["url"] if attrs.get("last_update"): obj.last_update = attrs["last_update"] if attrs.get("code") == obj.code: obj.code = attrs["code"] if attrs.get("title") == obj.title: obj.title = attrs["title"] if kwargs: # for Audit objects if kwargs.get("program") and kwargs.get("program").get("title"): obj.program = kwargs["program"]["title"] # for Assessment Template objects if kwargs.get("audit") and kwargs.get("audit").get("title"): obj.audit = kwargs["audit"]["title"] # for Assessment objects if kwargs.get("object") and kwargs.get("object").get("title"): obj.object = kwargs["object"]["title"] return obj def update_list_objs(self, list_old_objs, factory): """Update objects used old objects (list_old_objs) as target, entities factories as new attributes data generator, REST API as service for provide that. Return list of updated objects. """ list_new_objs = [factory.create() for _ in xrange(len(list_old_objs))] list_new_attrs = [ self.get_obj_attrs( self.client.update_object(href=old_obj.href, url=old_obj.url, title=new_obj.title, slug=new_obj.code)) for old_obj, new_obj in zip(list_old_objs, list_new_objs) ] return [ self.set_obj_attrs(new_attrs, new_obj) for new_attrs, new_obj in zip(list_new_attrs, list_new_objs) ]
class BaseRestService(object): """Base class for business layer's services objects.""" def __init__(self, endpoint): self.endpoint = endpoint self.client = RestClient(self.endpoint) self.entities_factory_cls = factory.get_cls_entity_factory( object_name=self.endpoint) def create_list_objs(self, entity_factory, count, attrs_to_factory=None, **attrs_for_template): """Create and return list of objects used entities factories, REST API service and attributes to make JSON template to request. As default entity factory is generating random objects, if 'attrs_for_factory' is not None then factory is generating objects according to 'attrs_for_factory' (dictionary of attributes). """ list_factory_objs = [entity_factory.create() for _ in xrange(count)] if attrs_to_factory: list_factory_objs = [ entity_factory.create(**attrs_to_factory) for _ in xrange(count) ] list_attrs = [ self.get_items_from_resp( self.client.create_object(**dict(factory_obj.__dict__.items() + attrs_for_template.items()))) for factory_obj in list_factory_objs ] return [ self.set_obj_attrs(attrs=attrs, obj=factory_obj, **attrs_for_template) for attrs, factory_obj in zip(list_attrs, list_factory_objs) ] def update_list_objs(self, entity_factory, list_objs_to_update, attrs_to_factory=None, **attrs_for_template): """Update and return list of objects used entities factories, REST API service and attributes to make JSON template to request. As default entity factory is generating random objects, if 'attrs_for_factory' is not None then factory is generating objects according to 'attrs_for_factory' (dictionary of attributes). """ list_new_objs = [ entity_factory.create() for _ in xrange(len(list_objs_to_update)) ] if attrs_to_factory: list_new_objs = [ entity_factory.create(**attrs_to_factory) for _ in xrange(len(list_objs_to_update)) ] list_new_attrs = [ self.get_items_from_resp( self.client.update_object( href=old_obj.href, **dict({ k: v for k, v in new_obj.__dict__.iteritems() if k != "href" }.items() + attrs_for_template.items()))) for old_obj, new_obj in zip(list_objs_to_update, list_new_objs) ] return [ self.set_obj_attrs(new_attrs, new_obj) for new_attrs, new_obj in zip(list_new_attrs, list_new_objs) ] @staticmethod def get_items_from_resp(response): """Check response from server and get items {key: value} from it.""" def get_extra_items(response): """Get extra items {key: value} that used in entities.""" extra = {} if response.get("selfLink"): extra.update({"href": response.get("selfLink")}) if response.get("viewLink"): extra.update({ "url": environment.APP_URL + response.get("viewLink")[1:] }) return extra resp = json.loads(response.text) if response.status_code == 200: # check response from server if (isinstance(resp, list) and len(resp[0]) == 2 and isinstance(resp[0][1], dict)): resp = resp[0][1] # [[201, {"k": "v"}]] to {"k": "v"} resp = resp.itervalues().next( ) # {"obj": {"k": "v"}} to {"k": "v"} return dict(resp.items() + get_extra_items(resp).items()) else: resp_code, resp_message = resp[0] raise exceptions.ContentDecodingError( messages.ExceptionsMessages.err_server_response.format( resp_code, resp_message)) @staticmethod def set_obj_attrs(attrs, obj, **kwargs): """Update object according to new attributes exclude "type", "contact", "owners" due of objects assertion specific, and keyword arguments - attributes witch used to make JSON template to request and witch contain fully objects descriptions as dictionary. """ obj.__dict__.update({ k: v for k, v in attrs.iteritems() if v and k not in ("type", "contact", "owners") }) if kwargs: # for Audit objects if kwargs.get("program"): obj.program = kwargs["program"] # for Assessment, Assessment Template, Issues objects if kwargs.get("audit"): obj.audit = kwargs["audit"] return obj def create_objs(self, count, factory_params=None, **attrs_for_template): """Create new objects via REST API and return list of created objects with filtered attributes. """ list_objs = self.create_list_objs( entity_factory=self.entities_factory_cls(), count=count, attrs_to_factory=factory_params, **attrs_for_template) return self.entities_factory_cls().filter_objs_attrs( objs=list_objs, attrs_to_include=self.entities_factory_cls().obj_attrs_names) def update_objs(self, objs, factory_params=None, **attrs_for_template): """Update existing objects via REST API and return list of updated objects with filtered attributes. """ list_objs = self.update_list_objs( entity_factory=self.entities_factory_cls(), list_objs_to_update=string_utils.convert_to_list(objs), attrs_to_factory=factory_params, **attrs_for_template) return self.entities_factory_cls().filter_objs_attrs( objs=list_objs, attrs_to_include=self.entities_factory_cls().obj_attrs_names) def delete_objs(self, objs): """Delete existing objects via REST API.""" return [ self.client.delete_object(href=obj.href) for obj in string_utils.convert_to_list(objs) ]