def _filter_fields(documents: [Document], filed_types=None): result = [] def expected_field(inc, f_ids): attr_type = path(inc, 'attributes.field_type') if filed_types is not None and attr_type not in filed_types: return False return inc['type'] == 'dictionary' and inc['id'] in f_ids for doc in documents: ids = [d['id'] for d in path(doc.relationships, 'fields.data', [])] fields = [i for i in doc.included if expected_field(i, ids)] for field in fields: f_type = path(field, 'attributes.field_type') f_text = f_type.capitalize() f_name = path(field, 'attributes.name') response = { 'id': f_name, 'name': f'{f_text} Field: {f_name}', 'icon_type': f_type, 'group': { 'id': doc['id'], # TODO: doc.id 'name': doc['name'], } } result.append(response) return result
def handle_connection(): """Handle bot connections. Gets notifications when the bot is added to a flow in an organization for the firs time. """ contents = request.get_json() if not isinstance(contents, dict): raise BadRequest('No input data provided') data = contents.get('data') if not data or not isinstance(data, dict): raise BadRequest('Invalid payload, missed "data"') should_disconnect = path(contents, 'meta.disconnected') or False org_uid = path(data, 'relationships.organization.data.id') if not org_uid: raise ValidationError('Organization id is missed') logger.info( 'Received %s webhook for organization %s' % (('disconnect' if should_disconnect else 'connect'), org_uid) ) if should_disconnect: disconnect(org_uid) message = 'Organization disconnected.' else: connect(Organization.from_id(org_uid)) message = 'Organization connected.' response = {'message': f'{message}'} return response, HTTPStatus.OK
def create_request(data: dict): transformer = SettingsTransformer() return Request( path(data, 'meta.organization.data.id'), path(data, 'data.relationships.organization_addon.data.id'), path(data, 'data.relationships.slate.data.id'), path(data, 'data.attributes.setting_name'), transformer.transform(path(data, 'data.attributes.settings')), )
def _transform_setting(self, setting: dict): setting_type = str(setting.get('type', '')) # TODO: radio_group_manual, multiple_choice, sequence # TODO: fields_mapping, match, mapping, group if setting_type in [self.CHOICE, self.RADIO_GROUP_MANUAL]: return path(setting, 'data.value') else: # Otherwise return the data or None return path(setting, 'data')
def documents_to_resource_fields(documents): result = [] for document in documents: field = models.Field( rf_id=path(document, 'id'), name=path(document, 'name'), ) result.append(field) return result
def field_to_resource_fields(fields): result = [] for field in fields: rf = models.Document( resource_id=path(field, 'id'), name=path(field, 'name'), resource_type=path(field, 'icon_type'), document_id=path(field, 'group.id'), document_name=path(field, 'group.name'), ) result.append(rf) return result
def from_collection(cls, obj): """ Create a list of instances of the current class from the provided data. """ if 'data' not in obj: raise MissingData() data = obj['data'] if len(data) == 0: return [] entities = [] for item in data: entity = cls(entity_id=None) if path(item, 'type', '') != entity.type: raise TypeMismatch() entity.__setstate__({ 'data': { 'id': path(item, 'id'), 'attributes': path(item, 'attributes', {}), 'relationships': path(item, 'relationships', {}), }, 'included': filter_included( path(item, 'relationships', {}), path(obj, 'included', []) ), 'meta': path(item, 'meta', {}), }) entities.append(entity) return entities
def fields(self, root): """Get all keys pointing to lists using `the_path` as a start point.""" result = [] first_object = path(self.contents, root) if isinstance(first_object, list) and len(first_object): first_object = first_object[0] if isinstance(first_object, dict): result = first_object.keys() return result
def create_storage(settings, org_id): if 'json_url' in settings: return JsonUrlStorage( url=settings['json_url'], user_agent=os.environ.get('CRAWLER_USER_AGENT'), timeout=int(os.environ.get('CRAWLER_TIMEOUT', 5)), ) if 'attachment' in settings: return JsonFileStorage(path(settings, 'attachment.file_id'), org_id) raise ValidationError('Invalid storage settings')
def to_dict(self): """Convert this model to a dictionary.""" tags = [] for name in path(self.data, 'names', []): tags.append({ 'type': 'flow_tags', 'attributes': { 'name': name, }, }) return {'data': tags}
def has_one(self, cls, relation_name): """Create an instance of the related entity. :param cls: The class of the related entity :param relation_name: The name of the relation defined in the ``relationships`` dictionary :return: An instance of the related entity if any or None """ if relation_name not in self.relationships: raise RelationNotExist() data = path(self.relationships, f'{relation_name}.data') if data is None: return None ids = (path(data, 'id'), path(data, 'type')) relations = [e for e in self.included if (e['id'], e['type']) == ids] if len(relations) == 0: return cls(path(data, 'id')) return cls.from_one({'data': relations})
def authenticate(org_uid: str, client_id: str, client_secret: str) -> AddonIdentity: client = Client(base_url=current_app.config.get('API_BASE_URI')) logger.info('Trying to authenticate bot %s for organization %s' % (client_id, org_uid)) # We're expect a response in the following format: # { # 'meta': { # 'token_type': 'Bearer', # 'expires': 1209000, # 'access_token': '...', # 'refresh_token': '...', # 'domain': '', # } # } # identity = client.addons.access_token(org_uid, client_id, client_secret) logger.info('Received identity response for organization %s: %s' % (org_uid, identity)) if 'meta' not in identity: raise BadRequest(message='The `meta` field is required.') token = path(identity, 'meta.access_token') domain = path(identity, 'meta.domain') expires = path(identity, 'meta.expires') if expires and token and domain: expires = datetime.utcnow() + timedelta(seconds=int(expires)) return AddonIdentity(token, domain, expires) fields = {'expires': expires, 'access_token': token, 'domain': domain} missed = [k for k in fields.keys() if not fields[k]] message = map(lambda f: f'The `meta.{f}` field is required.', missed) raise BadRequest(message=list(message))
def __setstate__(self, obj): """Play nice with pickle.""" self.attributes = path(obj, 'data.attributes', {}) self.attributes['id'] = path(obj, 'data.id') self.relationships = path(obj, 'data.relationships', {}) self.included = path(obj, 'included', []) self.meta = path(obj, 'meta', {}) self.object_meta = path(obj, 'data.meta', {})
def from_one(cls, obj): """Create an instance of the current class from the provided data.""" if 'data' not in obj: raise MissingData() entity = cls(entity_id=None) if path(obj, 'data.type') != entity.type: raise TypeMismatch() entity.__setstate__({ 'data': { 'id': path(obj, 'data.id'), 'attributes': path(obj, 'data.attributes', {}), 'relationships': path(obj, 'data.relationships', {}), 'meta': path(obj, 'data.meta', {}), }, 'included': filter_included( path(obj, 'data.relationships', {}), path(obj, 'included', []) ), 'meta': path(obj, 'meta', {}), }) return entity
def has_many(self, cls, relation_name): """Create a list of instances of the related entities. :param cls: The class of the related entity :param relation_name: The name of the relation defined in the ``relationships`` dictionary :return: A list of instances of the related entities """ if relation_name not in self.relationships: raise RelationNotExist() data = path(self.relationships, f'{relation_name}.data') if data is None: return [] ids = set((r['id'], r['type']) for r in data) relations = [e for e in self.included if (e['id'], e['type']) in ids] if len(relations) == 0: result = map(lambda x: cls(entity_id=x[0]), ids) return list(result) return cls.from_collection({'data': relations})
def expected_field(inc, f_ids): attr_type = path(inc, 'attributes.field_type') if filed_types is not None and attr_type not in filed_types: return False return inc['type'] == 'dictionary' and inc['id'] in f_ids
def simplify(relation): return ((d['type'], d['id']) for i in relation for d in normalize(path(relation, f'{i}.data')) if 'type' in d)