def test_restructure_behaviour_oriented_wiring_forwards(self): input_file, output_file, output_file_no_views = self._read_json_fixtures( "wiringstatus_v1.0", "wiringstatus_v2.0", "wiringstatus_v2.0_no_views" ) empty1_workspace = Mock(wiringStatus="{}") empty2_workspace = Mock(wiringStatus="") empty_v1_workspace = Mock(wiringStatus='{"connections": [], "operators": {}}') workspace = Mock(wiringStatus=json.dumps(input_file)) del input_file["views"] workspace_no_views = Mock(wiringStatus=json.dumps(input_file)) migration = self._pick_migration("0017_restructure_behaviour_oriented_wiring") orm = Mock(autospec=migration.orm()) orm.Workspace.objects.all.return_value = TestQueryResult( [empty1_workspace, empty2_workspace, empty_v1_workspace, workspace, workspace_no_views] ) migration.migration_instance().forwards(orm) from wirecloud.platform.wiring.utils import get_wiring_skeleton self.assertEqual(json.loads(empty1_workspace.wiringStatus), get_wiring_skeleton()) self.assertEqual(json.loads(empty2_workspace.wiringStatus), get_wiring_skeleton()) self.assertEqual(json.loads(empty_v1_workspace.wiringStatus), get_wiring_skeleton()) self.assertEqual(json.loads(workspace.wiringStatus), output_file) self.assertEqual(json.loads(workspace_no_views.wiringStatus), output_file_no_views) for workspace in orm.Workspace.objects.all(): self.assertEqual(workspace.save.call_count, 1)
def createEmptyWorkspace(workspaceName, user, allow_renaming=False): workspace = Workspace(name=workspaceName, creator=user, wiringStatus=get_wiring_skeleton()) if allow_renaming is True: save_alternative(Workspace, 'name', workspace) else: workspace.save() UserWorkspace.objects.create(user=user, workspace=workspace) # Tab creation createTab(_('Tab'), workspace) return workspace
def _parse_wiring_info(self, wiring_property='hasPlatformWiring'): if self._info['type'] == 'mashup': self._info['wiring'] = get_wiring_skeleton() else: self._info['wiring'] = {} self._info['wiring']['inputs'] = [] self._info['wiring']['outputs'] = [] # method self._graph.objects always returns an iterable object not subscriptable, # althought only exits one instance wiring_type = WIRE_M if self._info['type'] == 'mashup' else WIRE wiring_element = self._get_field(wiring_type, wiring_property, self._rootURI, id_=True, required=False) if self._info['type'] == 'mashup': self._info['wiring']['version'] = self._get_field(USDL, 'versionInfo', wiring_element, default="1.0", required=False) sorted_inputs = sorted(self._graph.objects(wiring_element, WIRE['hasInputEndpoint']), key=lambda source: possible_int(self._get_field(WIRE, 'index', source, required=False))) for input_endpoint in sorted_inputs: var_name = self._get_field(DCTERMS, 'title', input_endpoint, required=True) self._info['wiring']['inputs'].append({ 'name': var_name, 'type': self._get_field(WIRE, 'type', input_endpoint, required=True), 'label': self._get_translation_field(RDFS, 'label', input_endpoint, var_name + '_label', required=False, type='inputendpoint', variable=var_name, field='label'), 'description': self._get_translation_field(DCTERMS, 'description', input_endpoint, var_name + '_description', required=False, type='inputendpoint', variable=var_name, field='description'), 'actionlabel': self._get_translation_field(WIRE, 'inputActionLabel', input_endpoint, var_name + '_actionlabel', required=False, type='inputendpoint', variable=var_name, field='actionlabel'), 'friendcode': self._get_field(WIRE, 'friendcode', input_endpoint, required=False), }) sorted_outputs = sorted(self._graph.objects(wiring_element, WIRE['hasOutputEndpoint']), key=lambda output: possible_int(self._get_field(WIRE, 'index', output, required=False))) for output_endpoint in sorted_outputs: var_name = self._get_field(DCTERMS, 'title', output_endpoint, required=True) self._info['wiring']['outputs'].append({ 'name': var_name, 'type': self._get_field(WIRE, 'type', output_endpoint, required=True), 'label': self._get_translation_field(RDFS, 'label', output_endpoint, var_name + '_label', required=False, type='outputendpoint', variable=var_name, field='label'), 'description': self._get_translation_field(DCTERMS, 'description', output_endpoint, var_name + '_description', required=False, type='outputendpoint', variable=var_name, field='description'), 'friendcode': self._get_field(WIRE, 'friendcode', output_endpoint, required=False), }) if self._info['type'] == 'mashup': self._parse_wiring_connection_info(wiring_element) self._parse_wiring_operator_info(wiring_element) if self._info['wiring']['version'] == '1.0': self._parse_wiring_views(wiring_element) else: self._parse_wiring_behaviours(wiring_element)
def test_restructure_behaviour_oriented_wiring_forwards(self): input_file, output_file, output_file_no_views = self._read_json_fixtures( 'wiringstatus_v1.0', 'wiringstatus_v2.0', 'wiringstatus_v2.0_no_views') empty1_workspace = Mock(wiringStatus='{}') empty2_workspace = Mock(wiringStatus='') empty_v1_workspace = Mock( wiringStatus='{"connections": [], "operators": {}}') workspace = Mock(wiringStatus=json.dumps(input_file)) del input_file['views'] workspace_no_views = Mock(wiringStatus=json.dumps(input_file)) migration = self._pick_migration( '0017_restructure_behaviour_oriented_wiring') orm = Mock(autospec=migration.orm()) orm.Workspace.objects.all.return_value = TestQueryResult([ empty1_workspace, empty2_workspace, empty_v1_workspace, workspace, workspace_no_views ]) migration.migration_instance().forwards(orm) from wirecloud.platform.wiring.utils import get_wiring_skeleton self.assertEqual(json.loads(empty1_workspace.wiringStatus), get_wiring_skeleton()) self.assertEqual(json.loads(empty2_workspace.wiringStatus), get_wiring_skeleton()) self.assertEqual(json.loads(empty_v1_workspace.wiringStatus), get_wiring_skeleton()) self.assertEqual(json.loads(workspace.wiringStatus), output_file) self.assertEqual(json.loads(workspace_no_views.wiringStatus), output_file_no_views) for workspace in orm.Workspace.objects.all(): self.assertEqual(workspace.save.call_count, 1)
def createEmptyWorkspace(workspaceName, user, allow_renaming=False): workspace = Workspace(name=workspaceName, creator=user, wiringStatus=get_wiring_skeleton()) if allow_renaming is True: save_alternative(Workspace, 'name', workspace) else: workspace.full_clean(validate_unique=False) workspace.save() UserWorkspace.objects.create(user=user, workspace=workspace) # Tab creation createTab(_('Tab'), workspace) return workspace
def createEmptyWorkspace(title, user, allow_renaming=False, name=None): if name is None or name == '': name = URLify(title) workspace = Workspace(title=title, name=name, creator=user, wiringStatus=get_wiring_skeleton()) if allow_renaming is True: save_alternative(Workspace, 'name', workspace) else: workspace.save() UserWorkspace.objects.create(user=user, workspace=workspace) # Tab creation createTab(_('Tab'), workspace) return workspace
def createEmptyWorkspace(workspaceName, user, allow_renaming=False): active = False workspaces = UserWorkspace.objects.filter(user__id=user.id, active=True) if workspaces.count() == 0: # there isn't yet an active workspace active = True workspace = Workspace(name=workspaceName, creator=user, wiringStatus=get_wiring_skeleton()) if allow_renaming is True: save_alternative(Workspace, 'name', workspace) else: workspace.save() UserWorkspace.objects.create(user=user, workspace=workspace, active=active) # Tab creation createTab(_('Tab'), workspace) return workspace
def _parse_wiring_info(self, parse_connections=False): if self._info['type'] == 'mashup': self._info['wiring'] = get_wiring_skeleton() else: self._info['wiring'] = {} self._info['wiring']['inputs'] = [] self._info['wiring']['outputs'] = [] wiring_elements = self._xpath(WIRING_XPATH, self._doc) if len(wiring_elements) < 1: return wiring_element = wiring_elements[0] for slot in self._xpath(INPUT_ENDPOINT_XPATH, wiring_element): self._add_translation_index(slot.get('label'), type='inputendpoint', variable=slot.get('name')) self._add_translation_index(slot.get('actionlabel', ''), type='inputendpoint', variable=slot.get('name')) self._add_translation_index(slot.get('description', ''), type='inputendpoint', variable=slot.get('name')) self._info['wiring']['inputs'].append({ 'name': slot.get('name'), 'type': slot.get('type'), 'label': slot.get('label'), 'description': slot.get('description', ''), 'actionlabel': slot.get('actionlabel', slot.get('action_label', '')), 'friendcode': slot.get('friendcode'), }) for event in self._xpath(OUTPUT_ENDPOINT_XPATH, wiring_element): self._add_translation_index(event.get('label'), type='outputendpoint', variable=event.get('name')) self._add_translation_index(event.get('description', ''), type='outputendpoint', variable=event.get('name')) self._info['wiring']['outputs'].append({ 'name': event.get('name'), 'type': event.get('type'), 'label': event.get('label'), 'description': event.get('description', ''), 'friendcode': event.get('friendcode'), }) if parse_connections: self._parse_wiring_connection_info(wiring_element) self._parse_wiring_operator_info(wiring_element)
def forwards(self, orm): for workspace in orm.Workspace.objects.all(): # check if this wiring status is empty string if not workspace.wiringStatus: wiring_status = {} else: wiring_status = json.loads(workspace.wiringStatus) # check if this wiring status is empty object if not wiring_status: workspace.wiringStatus = json.dumps(get_wiring_skeleton()) workspace.save() continue # check if this wiring status is old version (1.0) if not self._need_to_upgrade(wiring_status): continue new_version = parse_wiring_old_version(wiring_status) workspace.wiringStatus = json.dumps(new_version) workspace.save()
def fillWorkspaceUsingTemplate(workspace, template): if not isinstance(template, TemplateParser): template = TemplateParser(template) if template.get_resource_type() != 'mashup': raise TypeError('Unsupported resource type: %s' % template.get_resource_type()) user = workspace.creator context_values = get_context_values(workspace, workspace.creator) processor = TemplateValueProcessor({'user': user, 'context': context_values}) mashup_description = template.get_resource_info() new_values = {} id_mapping = { 'operator': {}, 'widget': {}, } for preference_name in mashup_description['preferences']: # Filter public and sharelist preferences if preference_name in ("public", "sharelist"): continue new_values[preference_name] = { 'inherit': False, 'value': mashup_description['preferences'][preference_name], } if len(new_values) > 0: update_workspace_preferences(workspace, new_values) new_forced_values = { 'extra_prefs': [], 'iwidget': {}, 'ioperator': {}, } for param in mashup_description['params']: new_forced_values['extra_prefs'].append({ 'name': param['name'], 'inheritable': False, 'label': param.get('label'), 'type': param.get('type'), 'description': param.get('description'), 'required': param.get('required'), }) for tab_entry in mashup_description['tabs']: tab = createTab(tab_entry.get('title'), workspace, name=tab_entry['name'], allow_renaming=True) new_values = {} for preference_name in tab_entry['preferences']: new_values[preference_name] = { 'inherit': False, 'value': tab_entry['preferences'][preference_name], } if len(new_values) > 0: update_tab_preferences(tab, new_values) for resource in tab_entry['resources']: position = resource['position'] rendering = resource['rendering'] widget = get_or_add_widget_from_catalogue(resource.get('vendor'), resource.get('name'), resource.get('version'), user) iwidget_data = { "widget": widget.uri, "title": resource.get('title'), "left": float(position.get('x')), "top": float(position.get('y')), "icon_left": 0, "icon_top": 0, "zIndex": int(position.get('z')), "width": float(rendering.get('width')), "height": float(rendering.get('height')), "layout": int(rendering.get('layout')), "minimized": rendering['minimized'], "fulldragboard": rendering['fulldragboard'], "titlevisible": rendering['titlevisible'], } iwidget = SaveIWidget(iwidget_data, user, tab, commit=False) if resource.get('readonly'): iwidget.readOnly = True initial_variable_values = {} iwidget_forced_values = {} iwidget_info = widget.resource.get_processed_info(process_variables=True) for prop_name in resource['properties']: prop = resource['properties'][prop_name] read_only = prop.get('readonly') if prop.get('value', None) is not None: value = prop['value'] else: value = iwidget_info['variables']['properties'][prop_name]['default'] if read_only: iwidget_forced_values[prop_name] = {'value': value} else: initial_variable_values[prop_name] = processor.process(value) for pref_name in resource['preferences']: pref = resource['preferences'][pref_name] read_only = pref.get('readonly') if pref.get('value', None) is not None: value = pref['value'] if isinstance(value, dict): value = value["users"].get("%s" % workspace.creator.id, iwidget_info['variables']['preferences'][pref_name]['default']) else: value = iwidget_info['variables']['preferences'][pref_name]['default'] # Build multiuser structure if read_only: iwidget_forced_values[pref_name] = {'value': value, 'hidden': pref.get('hidden', False)} else: initial_variable_values[pref_name] = processor.process(value) set_initial_values(iwidget, initial_variable_values, iwidget_info, workspace.creator) iwidget.save() if len(iwidget_forced_values) > 0: new_forced_values['iwidget'][str(iwidget.id)] = iwidget_forced_values id_mapping['widget'][resource.get('id')] = { 'id': iwidget.id, 'name': resource.get('vendor') + "/" + resource.get('name') + "/" + resource.get('version') } # wiring if len(workspace.wiringStatus) == 0: workspace.wiringStatus = get_wiring_skeleton() max_id = 0 for id_ in workspace.wiringStatus['operators'].keys(): if int(id_) > max_id: max_id = int(id_) # Process operators info for operator_id, operator in mashup_description['wiring']['operators'].items(): max_id += 1 new_id = "%s" % max_id id_mapping['operator'][operator_id] = { 'id': new_id } workspace.wiringStatus['operators'][new_id] = { 'id': new_id, 'name': operator['name'], 'preferences': operator['preferences'], 'properties': {} } ioperator_forced_values = {} for pref_id, pref in operator['preferences'].items(): if pref.get('readonly', False): ioperator_forced_values[pref_id] = {'value': pref.get('value'), 'hidden': pref.get('hidden', False)} workspace.wiringStatus['operators'][new_id]["preferences"][pref_id]["value"] = {'users': {"%s" % workspace.creator.id: pref["value"]}} if len(ioperator_forced_values) > 0: new_forced_values['ioperator'][new_id] = ioperator_forced_values # Remap connection ids source_mapping = {} target_mapping = {} for connection in mashup_description['wiring']['connections']: if not is_valid_connection(connection, id_mapping): continue old_source_name = get_endpoint_name(connection['source']) old_target_name = get_endpoint_name(connection['target']) connection['source']['id'] = map_id(connection['source'], id_mapping) connection['target']['id'] = map_id(connection['target'], id_mapping) source_mapping[old_source_name] = get_endpoint_name(connection['source']) target_mapping[old_target_name] = get_endpoint_name(connection['target']) # Add new connection workspace.wiringStatus['connections'].append(connection) # Merging visual description... _remap_component_ids(id_mapping, mashup_description['wiring']['visualdescription']['components'], isGlobal=True) _remap_connection_endpoints(source_mapping, target_mapping, mashup_description['wiring']['visualdescription']) # Remap mashup description behaviours' ids if len(mashup_description['wiring']['visualdescription']['behaviours']) != 0: for behaviour in mashup_description['wiring']['visualdescription']['behaviours']: _remap_component_ids(id_mapping, behaviour['components']) _remap_connection_endpoints(source_mapping, target_mapping, behaviour) if len(workspace.wiringStatus['visualdescription']['behaviours']) != 0 or len(mashup_description['wiring']['visualdescription']['behaviours']) != 0: if len(workspace.wiringStatus['visualdescription']['behaviours']) == 0 and not is_empty_wiring(workspace.wiringStatus['visualdescription']): # *TODO* flag to check if the user really want to merge both workspaces. _create_new_behaviour(workspace.wiringStatus['visualdescription'], _("Original wiring"), _("This is the wiring description of the original workspace")) if len(mashup_description['wiring']['visualdescription']['behaviours']) == 0: _create_new_behaviour(mashup_description['wiring']['visualdescription'], _("Merged wiring"), _("This is the wiring description of the merged mashup.")) workspace.wiringStatus['visualdescription']['behaviours'] += mashup_description['wiring']['visualdescription']['behaviours'] # Merge global behaviour components and connections workspace.wiringStatus['visualdescription']['components']['operator'].update(mashup_description['wiring']['visualdescription']['components']['operator']) workspace.wiringStatus['visualdescription']['components']['widget'].update(mashup_description['wiring']['visualdescription']['components']['widget']) workspace.wiringStatus['visualdescription']['connections'] += mashup_description['wiring']['visualdescription']['connections'] # Forced values normalize_forced_values(workspace) workspace.forcedValues['extra_prefs'] += new_forced_values['extra_prefs'] workspace.forcedValues['iwidget'].update(new_forced_values['iwidget']) workspace.forcedValues['ioperator'].update(new_forced_values['ioperator']) workspace.save()
def build_json_template_from_workspace(options, workspace, user): options['type'] = 'mashup' options['params'] = [] options['embedmacs'] = options.get('embedmacs', False) is True options['embedded'] = set() options['translations'] = {} options['translation_index_usage'] = {} description = options.get('description', '').strip() if description == '': options['description'] = get_workspace_description(workspace) if 'authors' not in options: options['authors'] = ({'name': six.text_type(user)}, ) elif isinstance(options['authors'], six.text_type): options['authors'] = parse_contacts_info(options['authors']) if 'contributors' not in options: options['contributors'] = () elif isinstance(options['contributors'], six.text_type): options['contributors'] = parse_contacts_info(options['contributors']) options['requirements'] = [] readOnlyWidgets = options.get('readOnlyWidgets', False) parametrization = options.get('parametrization') if not parametrization: parametrization = {} if 'iwidgets' not in parametrization: parametrization['iwidgets'] = {} if 'ioperators' not in parametrization: parametrization['ioperators'] = {} # Workspace preferences options['preferences'] = {} for preference in workspace.workspacepreference_set.all(): if not preference.inherit: options['preferences'][preference.name] = preference.value # Tabs and their preferences options['tabs'] = [] options['wiring'] = { 'inputs': [], 'outputs': [], } for tab in workspace.tab_set.order_by('position'): preferences = {} for preference in tab.tabpreference_set.all(): if not preference.inherit: preferences[preference.name] = preference.value resources = [] for iwidget in tab.iwidget_set.select_related( 'widget__resource').all(): resource_info = process_iwidget(workspace, iwidget, options['wiring'], parametrization['iwidgets'], readOnlyWidgets) resources.append(resource_info) if options['embedmacs']: options['embedded'].add('/'.join( (resource_info['vendor'], resource_info['name'], resource_info['version']))) options['tabs'].append({ 'name': tab.name, 'resources': resources, 'preferences': preferences, }) # wiring conections and operators readOnlyConnectables = options.get('readOnlyConnectables', False) wiring_status = workspace.wiringStatus if len(wiring_status) == 0: wiring_status = get_wiring_skeleton() # Set the wiring status' version if wiring_status.get('version', '1.0') == '1.0': wiring_status = parse_wiring_old_version(wiring_status) options['wiring']['version'] = '2.0' options['wiring']['operators'] = {} for id_, operator in six.iteritems(wiring_status['operators']): operator_data = { 'name': operator['name'], 'preferences': {}, } vendor, name, version = operator['name'].split('/') resource = CatalogueResource.objects.get(vendor=vendor, short_name=name, version=version) operator_info = json.loads(resource.json_description) operator_params = parametrization['ioperators'].get(id_, {}) for pref_index, preference in enumerate(operator_info['preferences']): status = 'normal' if preference['name'] in operator_params: ioperator_param_desc = operator_params[preference['name']] status = ioperator_param_desc.get('status', 'normal') source = ioperator_param_desc.get('source', 'current') if source == 'default': if status == 'normal': # Do not issue a Preference element for this preference continue value = None elif source == 'current': value = get_current_operator_pref_value( operator, preference) elif source == 'custom': value = ioperator_param_desc['value'] else: raise Exception('Invalid preference value source: %s' % source) else: value = get_current_operator_pref_value(operator, preference) operator_data['preferences'][preference['name']] = { 'readonly': status != 'normal', 'hidden': status == 'hidden', } if value is not None: operator_data['preferences'][ preference['name']]['value'] = value options['wiring']['operators'][id_] = operator_data if options['embedmacs']: options['embedded'].add(operator['name']) options['wiring']['connections'] = [] for connection in wiring_status['connections']: options['wiring']['connections'].append({ 'source': connection['source'], 'target': connection['target'], 'readonly': readOnlyConnectables, }) options['wiring']['visualdescription'] = wiring_status['visualdescription'] embedded = options['embedded'] options['embedded'] = [] for resource in embedded: (vendor, name, version) = resource.split('/') options['embedded'].append({ 'vendor': vendor, 'name': name, 'version': version, 'src': 'macs/%s_%s_%s.wgt' % (vendor, name, version) }) del options['embedmacs'] return options
def build_json_template_from_workspace(options, workspace, user): options['type'] = 'mashup' options['params'] = [] options['embedmacs'] = options.get('embedmacs', False) is True options['embedded'] = set() options['translations'] = {} options['translation_index_usage'] = {} description = options.get('description', '').strip() if description == '': options['description'] = get_workspace_description(workspace) if 'authors' not in options: options['authors'] = ({'name': six.text_type(user)},) elif isinstance(options['authors'], six.text_type): options['authors'] = parse_contacts_info(options['authors']) if 'contributors' not in options: options['contributors'] = () elif isinstance(options['contributors'], six.text_type): options['contributors'] = parse_contacts_info(options['contributors']) options['requirements'] = [] readOnlyWidgets = options.get('readOnlyWidgets', False) parametrization = options.get('parametrization') if not parametrization: parametrization = {} if 'iwidgets' not in parametrization: parametrization['iwidgets'] = {} if 'ioperators' not in parametrization: parametrization['ioperators'] = {} # Workspace preferences options['preferences'] = {} for preference in workspace.workspacepreference_set.all(): if not preference.inherit: options['preferences'][preference.name] = preference.value # Tabs and their preferences options['tabs'] = [] options['wiring'] = { 'inputs': [], 'outputs': [], } for tab in workspace.tab_set.order_by('position'): preferences = {} for preference in tab.tabpreference_set.all(): if not preference.inherit: preferences[preference.name] = preference.value resources = [] for iwidget in tab.iwidget_set.select_related('widget__resource').all(): resource_info = process_iwidget(workspace, iwidget, options['wiring'], parametrization['iwidgets'], readOnlyWidgets) resources.append(resource_info) if options['embedmacs']: options['embedded'].add('/'.join((resource_info['vendor'], resource_info['name'], resource_info['version']))) options['tabs'].append({ 'name': tab.name, 'resources': resources, 'preferences': preferences, }) # wiring conections and operators readOnlyConnectables = options.get('readOnlyConnectables', False) wiring_status = workspace.wiringStatus if len(wiring_status) == 0: wiring_status = get_wiring_skeleton() # Set the wiring status' version if wiring_status.get('version', '1.0') == '1.0': wiring_status = parse_wiring_old_version(wiring_status) options['wiring']['version'] = '2.0' options['wiring']['operators'] = {} for id_, operator in six.iteritems(wiring_status['operators']): operator_data = { 'name': operator['name'], 'preferences': {}, } vendor, name, version = operator['name'].split('/') resource = CatalogueResource.objects.get(vendor=vendor, short_name=name, version=version) operator_info = json.loads(resource.json_description) operator_params = parametrization['ioperators'].get(id_, {}) for pref_index, preference in enumerate(operator_info['preferences']): status = 'normal' if preference['name'] in operator_params: ioperator_param_desc = operator_params[preference['name']] status = ioperator_param_desc.get('status', 'normal') source = ioperator_param_desc.get('source', 'current') if source == 'default': if status == 'normal': # Do not issue a Preference element for this preference continue value = None elif source == 'current': value = get_current_operator_pref_value(operator, preference) elif source == 'custom': value = ioperator_param_desc['value'] else: raise Exception('Invalid preference value source: %s' % source) else: value = get_current_operator_pref_value(operator, preference) operator_data['preferences'][preference['name']] = { 'readonly': status != 'normal', 'hidden': status == 'hidden', } if value is not None: operator_data['preferences'][preference['name']]['value'] = value options['wiring']['operators'][id_] = operator_data if options['embedmacs']: options['embedded'].add(operator['name']) options['wiring']['connections'] = [] for connection in wiring_status['connections']: options['wiring']['connections'].append({ 'source': connection['source'], 'target': connection['target'], 'readonly': readOnlyConnectables, }) options['wiring']['visualdescription'] = wiring_status['visualdescription'] embedded = options['embedded'] options['embedded'] = [] for resource in embedded: (vendor, name, version) = resource.split('/') options['embedded'].append({ 'vendor': vendor, 'name': name, 'version': version, 'src': 'macs/%s_%s_%s.wgt' % (vendor, name, version) }) del options['embedmacs'] return options
def fillWorkspaceUsingTemplate(workspace, template): if not isinstance(template, TemplateParser): template = TemplateParser(template) if template.get_resource_type() != 'mashup': raise TypeError('Unsupported resource type: %s' % template.get_resource_type()) user = workspace.creator context_values = get_context_values(workspace, workspace.creator) processor = TemplateValueProcessor({'user': user, 'context': context_values}) mashup_description = template.get_resource_info() new_values = {} id_mapping = { 'operator': {}, 'widget': {}, } for preference_name in mashup_description['preferences']: new_values[preference_name] = { 'inherit': False, 'value': mashup_description['preferences'][preference_name], } if len(new_values) > 0: update_workspace_preferences(workspace, new_values) new_forced_values = { 'extra_prefs': [], 'iwidget': {}, 'ioperator': {}, } for param in mashup_description['params']: new_forced_values['extra_prefs'].append({ 'name': param['name'], 'inheritable': False, 'label': param.get('label'), 'type': param.get('type'), }) for tab_entry in mashup_description['tabs']: tab = createTab(tab_entry.get('name'), workspace, allow_renaming=True) new_values = {} for preference_name in tab_entry['preferences']: new_values[preference_name] = { 'inherit': False, 'value': tab_entry['preferences'][preference_name], } if len(new_values) > 0: update_tab_preferences(tab, new_values) for resource in tab_entry['resources']: position = resource['position'] rendering = resource['rendering'] widget = get_or_add_widget_from_catalogue(resource.get('vendor'), resource.get('name'), resource.get('version'), user) iwidget_data = { "widget": widget.uri, "title": resource.get('title'), "left": int(position.get('x')), "top": int(position.get('y')), "icon_left": 0, "icon_top": 0, "zIndex": int(position.get('z')), "width": int(rendering.get('width')), "height": int(rendering.get('height')), "layout": int(rendering.get('layout')), "minimized": rendering['minimized'], "fulldragboard": rendering['fulldragboard'], } iwidget = SaveIWidget(iwidget_data, user, tab, commit=False) if resource.get('readonly'): iwidget.readOnly = True initial_variable_values = {} iwidget_forced_values = {} iwidget_info = widget.resource.get_processed_info(process_variables=True) for prop_name in resource['properties']: prop = resource['properties'][prop_name] read_only = prop.get('readonly') if prop.get('value', None) is not None: value = prop['value'] else: value = iwidget_info['variables']['properties'][prop_name]['default'] if read_only: iwidget_forced_values[prop_name] = {'value': value} else: initial_variable_values[prop_name] = processor.process(value) for pref_name in resource['preferences']: pref = resource['preferences'][pref_name] read_only = pref.get('readonly') if pref.get('value', None) is not None: value = pref['value'] else: value = iwidget_info['variables']['preferences'][pref_name]['default'] if read_only: iwidget_forced_values[pref_name] = {'value': value, 'hidden': pref.get('hidden', False)} else: initial_variable_values[pref_name] = processor.process(value) set_initial_values(iwidget, initial_variable_values, iwidget_info) iwidget.save() if len(iwidget_forced_values) > 0: new_forced_values['iwidget'][six.text_type(iwidget.id)] = iwidget_forced_values id_mapping['widget'][resource.get('id')] = { 'id': iwidget.id, 'name': resource.get('vendor') + "/" + resource.get('name') + "/" + resource.get('version') } # wiring if len(workspace.wiringStatus) == 0: workspace.wiringStatus = get_wiring_skeleton() max_id = 0 for id_ in workspace.wiringStatus['operators'].keys(): if int(id_) > max_id: max_id = int(id_) # Process operators info for operator_id, operator in six.iteritems(mashup_description['wiring']['operators']): max_id += 1 new_id = "%s" % max_id id_mapping['operator'][operator_id] = { 'id': new_id } workspace.wiringStatus['operators'][new_id] = { 'id': new_id, 'name': operator['name'], 'preferences': operator['preferences'], } ioperator_forced_values = {} for pref_id, pref in six.iteritems(operator['preferences']): if pref.get('readonly', False): ioperator_forced_values[pref_id] = {'value': pref.get('value'), 'hidden': pref.get('hidden', False)} if len(ioperator_forced_values) > 0: new_forced_values['ioperator'][new_id] = ioperator_forced_values # Remap connection ids source_mapping = {} target_mapping = {} for connection in mashup_description['wiring']['connections']: old_source_name = get_endpoint_name(connection['source']) old_target_name = get_endpoint_name(connection['target']) connection['source']['id'] = map_id(connection['source'], id_mapping) connection['target']['id'] = map_id(connection['target'], id_mapping) source_mapping[old_source_name] = get_endpoint_name(connection['source']) target_mapping[old_target_name] = get_endpoint_name(connection['target']) # Add new connections workspace.wiringStatus['connections'] += mashup_description['wiring']['connections'] # Merging visual description... _remap_component_ids(id_mapping, mashup_description['wiring']['visualdescription']['components'], isGlobal=True) _remap_connection_endpoints(source_mapping, target_mapping, mashup_description['wiring']['visualdescription']) # Remap mashup description behaviours' ids if len(mashup_description['wiring']['visualdescription']['behaviours']) != 0: for behaviour in mashup_description['wiring']['visualdescription']['behaviours']: _remap_component_ids(id_mapping, behaviour['components']) _remap_connection_endpoints(source_mapping, target_mapping, behaviour) if len(workspace.wiringStatus['visualdescription']['behaviours']) != 0 or len(mashup_description['wiring']['visualdescription']['behaviours']) != 0: if len(workspace.wiringStatus['visualdescription']['behaviours']) == 0 and not is_empty_wiring(workspace.wiringStatus['visualdescription']): # *TODO* flag to check if the user really want to merge both workspaces. _create_new_behaviour(workspace.wiringStatus['visualdescription'], _("Original wiring"), _("This is the wiring description of the original workspace")) if len(mashup_description['wiring']['visualdescription']['behaviours']) == 0: _create_new_behaviour(mashup_description['wiring']['visualdescription'], _("Merged wiring"), _("This is the wiring description of the merged mashup.")) workspace.wiringStatus['visualdescription']['behaviours'] += mashup_description['wiring']['visualdescription']['behaviours'] # Merge global behaviour components and connections workspace.wiringStatus['visualdescription']['components']['operator'].update(mashup_description['wiring']['visualdescription']['components']['operator']) workspace.wiringStatus['visualdescription']['components']['widget'].update(mashup_description['wiring']['visualdescription']['components']['widget']) workspace.wiringStatus['visualdescription']['connections'] += mashup_description['wiring']['visualdescription']['connections'] # Forced values normalize_forced_values(workspace) workspace.forcedValues['extra_prefs'] += new_forced_values['extra_prefs'] workspace.forcedValues['iwidget'].update(new_forced_values['iwidget']) workspace.forcedValues['ioperator'].update(new_forced_values['ioperator']) workspace.save()
def fillWorkspaceUsingTemplate(workspace, template): if not isinstance(template, TemplateParser): template = TemplateParser(template) if template.get_resource_type() != "mashup": raise TypeError("Unsupported resource type: %s" % template.get_resource_type()) user = workspace.creator context_values = get_context_values(workspace, workspace.creator) processor = TemplateValueProcessor({"user": user, "context": context_values}) mashup_description = template.get_resource_info() new_values = {} id_mapping = {"operator": {}, "widget": {}} for preference_name in mashup_description["preferences"]: new_values[preference_name] = {"inherit": False, "value": mashup_description["preferences"][preference_name]} if len(new_values) > 0: update_workspace_preferences(workspace, new_values) new_forced_values = {"extra_prefs": [], "iwidget": {}, "ioperator": {}} for param in mashup_description["params"]: new_forced_values["extra_prefs"].append( {"name": param["name"], "inheritable": False, "label": param.get("label"), "type": param.get("type")} ) for tab_entry in mashup_description["tabs"]: tab = createTab(tab_entry.get("name"), workspace, allow_renaming=True) new_values = {} for preference_name in tab_entry["preferences"]: new_values[preference_name] = {"inherit": False, "value": tab_entry["preferences"][preference_name]} if len(new_values) > 0: update_tab_preferences(tab, new_values) for resource in tab_entry["resources"]: position = resource["position"] rendering = resource["rendering"] widget = get_or_add_widget_from_catalogue( resource.get("vendor"), resource.get("name"), resource.get("version"), user ) iwidget_data = { "left": int(position.get("x")), "top": int(position.get("y")), "icon_left": 0, "icon_top": 0, "zIndex": int(position.get("z")), "width": int(rendering.get("width")), "height": int(rendering.get("height")), "title": resource.get("title"), "layout": int(rendering.get("layout")), "widget": widget.uri, } iwidget = SaveIWidget(iwidget_data, user, tab, commit=False) if resource.get("readonly"): iwidget.readOnly = True initial_variable_values = {} iwidget_forced_values = {} iwidget_info = widget.resource.get_processed_info(process_variables=True) for prop_name in resource["properties"]: prop = resource["properties"][prop_name] read_only = prop.get("readonly") if prop.get("value", None) is not None: value = prop["value"] else: value = iwidget_info["variables"]["properties"][prop_name]["default"] if read_only: iwidget_forced_values[prop_name] = {"value": value} else: initial_variable_values[prop_name] = processor.process(value) for pref_name in resource["preferences"]: pref = resource["preferences"][pref_name] read_only = pref.get("readonly") if pref.get("value", None) is not None: value = pref["value"] else: value = iwidget_info["variables"]["preferences"][pref_name]["default"] if read_only: iwidget_forced_values[pref_name] = {"value": value, "hidden": pref.get("hidden", False)} else: initial_variable_values[pref_name] = processor.process(value) set_initial_values(iwidget, initial_variable_values, iwidget_info) iwidget.save() if len(iwidget_forced_values) > 0: new_forced_values["iwidget"][six.text_type(iwidget.id)] = iwidget_forced_values id_mapping["widget"][resource.get("id")] = { "id": iwidget.id, "name": resource.get("vendor") + "/" + resource.get("name") + "/" + resource.get("version"), } # wiring if len(workspace.wiringStatus) == 0: workspace.wiringStatus = get_wiring_skeleton() max_id = 0 for id_ in workspace.wiringStatus["operators"].keys(): if int(id_) > max_id: max_id = int(id_) # Process operators info for operator_id, operator in six.iteritems(mashup_description["wiring"]["operators"]): max_id += 1 new_id = "%s" % max_id id_mapping["operator"][operator_id] = {"id": new_id} workspace.wiringStatus["operators"][new_id] = { "id": new_id, "name": operator["name"], "preferences": operator["preferences"], } ioperator_forced_values = {} for pref_id, pref in six.iteritems(operator["preferences"]): if pref.get("readonly", False): ioperator_forced_values[pref_id] = {"value": pref.get("value"), "hidden": pref.get("hidden", False)} if len(ioperator_forced_values) > 0: new_forced_values["ioperator"][new_id] = ioperator_forced_values # Remap connection ids source_mapping = {} target_mapping = {} for connection in mashup_description["wiring"]["connections"]: old_source_name = get_endpoint_name(connection["source"]) old_target_name = get_endpoint_name(connection["target"]) connection["source"]["id"] = map_id(connection["source"], id_mapping) connection["target"]["id"] = map_id(connection["target"], id_mapping) source_mapping[old_source_name] = get_endpoint_name(connection["source"]) target_mapping[old_target_name] = get_endpoint_name(connection["target"]) # Add new connections workspace.wiringStatus["connections"] += mashup_description["wiring"]["connections"] # Merging visual description... _remap_component_ids(id_mapping, mashup_description["wiring"]["visualdescription"]["components"], isGlobal=True) _remap_connection_endpoints(source_mapping, target_mapping, mashup_description["wiring"]["visualdescription"]) # Remap mashup description behaviours' ids if len(mashup_description["wiring"]["visualdescription"]["behaviours"]) != 0: for behaviour in mashup_description["wiring"]["visualdescription"]["behaviours"]: _remap_component_ids(id_mapping, behaviour["components"]) _remap_connection_endpoints(source_mapping, target_mapping, behaviour) if ( len(workspace.wiringStatus["visualdescription"]["behaviours"]) != 0 or len(mashup_description["wiring"]["visualdescription"]["behaviours"]) != 0 ): if len(workspace.wiringStatus["visualdescription"]["behaviours"]) == 0 and not is_empty_wiring( workspace.wiringStatus["visualdescription"] ): # *TODO* flag to check if the user really want to merge both workspaces. _create_new_behaviour( workspace.wiringStatus["visualdescription"], _("Original wiring"), _("This is the wiring description of the original workspace"), ) if len(mashup_description["wiring"]["visualdescription"]["behaviours"]) == 0: _create_new_behaviour( mashup_description["wiring"]["visualdescription"], _("Merged wiring"), _("This is the wiring description of the merged mashup."), ) workspace.wiringStatus["visualdescription"]["behaviours"] += mashup_description["wiring"]["visualdescription"][ "behaviours" ] # Merge global behaviour components and connections workspace.wiringStatus["visualdescription"]["components"]["operator"].update( mashup_description["wiring"]["visualdescription"]["components"]["operator"] ) workspace.wiringStatus["visualdescription"]["components"]["widget"].update( mashup_description["wiring"]["visualdescription"]["components"]["widget"] ) workspace.wiringStatus["visualdescription"]["connections"] += mashup_description["wiring"]["visualdescription"][ "connections" ] # Forced values normalize_forced_values(workspace) workspace.forcedValues["extra_prefs"] += new_forced_values["extra_prefs"] workspace.forcedValues["iwidget"].update(new_forced_values["iwidget"]) workspace.forcedValues["ioperator"].update(new_forced_values["ioperator"]) workspace.save()
def _init(self): self._check_string_fields(('title', 'description', 'longdescription', 'email', 'homepage','doc', 'changelog', 'image', 'smartphoneimage', 'license', 'licenseurl', 'issuetracker')) self._check_contacts_fields(('authors', 'contributors')) # Normalize/check preferences and properties (only for widgets and operators) if self._info['type'] != 'mashup': self._check_array_fields(('preferences', 'properties')) for preference in self._info['preferences']: self._check_string_fields(('name', 'type'), place=preference, required=True) self._check_string_fields(('label', 'description', 'default'), place=preference) self._check_boolean_fields(('readonly', 'secure'), place=preference, default=False) self._check_string_fields(('value',), place=preference, null=True, default=None) for prop in self._info['properties']: self._check_string_fields(('name', 'type'), place=prop, required=True) self._check_string_fields(('label', 'description', 'default'), place=prop) self._check_boolean_fields(('secure',), place=prop, default=False) if self._info['type'] == 'widget': self._check_array_fields(('altcontents',)) if self._info.get('contents', None) is None: raise TemplateParseException('Missing widget content info') if not isinstance(self._info['contents'], dict): raise TemplateParseException('Content info must be an object') self._check_contents_field(self._info['contents'], alternative=False) for altcontent in self._info['altcontents']: self._check_contents_field(altcontent) elif self._info['type'] == 'mashup': self._check_array_fields(('params', 'embedded')) for resource in self._info['embedded']: if isinstance(resource, dict): self._check_string_fields(('vendor', 'name', 'version', 'src'), place=resource, required=True) else: raise TemplateParseException('embedded resource info must be an object') if 'wiring' not in self._info: self._info['wiring'] = get_wiring_skeleton() self._check_string_fields(('version',), place=self._info['wiring'], default='1.0') if self._info['wiring']['version'] == '1.0': # TODO: update to the new wiring format inputs = self._info['wiring']['inputs'] outputs = self._info['wiring']['outputs'] self._info['wiring'] = parse_wiring_old_version(self._info['wiring']) self._info['wiring']['inputs'] = inputs self._info['wiring']['outputs'] = outputs # END TODO elif self._info['wiring']['version'] == '2.0': if 'visualdescription' not in self._info['wiring']: self._info['wiring']['visualdescription'] = {} self._check_array_fields('behaviours', place=self._info['wiring']['visualdescription'], required=False) self._check_behaviour_view_fields(self._info['wiring']['visualdescription']) for behaviour in self._info['wiring']['visualdescription']['behaviours']: self._check_behaviour_view_fields(behaviour) if not 'wiring' in self._info: self._info['wiring'] = {} self._check_array_fields(('inputs', 'outputs'), place=self._info['wiring'], required=False) # Translations self._check_string_fields(('default_lang',), default='en') self._info['translation_index_usage'] = {} if 'translations' not in self._info: self._info['translations'] = {} self._add_translation_index(self._info['title'], type='resource', field='title') self._add_translation_index(self._info['description'], type='resource', field='description') if self._info['type'] != 'mashup': for preference in self._info['preferences']: self._add_translation_index(preference['label'], type='vdef', variable=preference['name'], field='label') self._add_translation_index(preference['description'], type='vdef', variable=preference['name'], field='description') if preference['type'] == 'list': for option_index, option in enumerate(preference['options']): self._add_translation_index(option['label'], type='upo', variable=preference['name'], option=option_index) for prop in self._info['properties']: self._add_translation_index(prop['label'], type='vdef', variable=prop['name'], field='label') self._add_translation_index(prop['description'], type='vdef', variable=prop['name'], field='description') for input_endpoint in self._info['wiring']['inputs']: self._check_string_fields(('name', 'type'), required=True, place=input_endpoint) self._check_string_fields(('label', 'description', 'actionlabel', 'friendcode'), place=input_endpoint) self._add_translation_index(input_endpoint['label'], type='inputendpoint', variable=input_endpoint['name'], field='label') self._add_translation_index(input_endpoint['description'], type='inputendpoint', variable=input_endpoint['name'], field='description') self._add_translation_index(input_endpoint['actionlabel'], type='inputendpoint', variable=input_endpoint['name'], field='actionlabel') for output_endpoint in self._info['wiring']['outputs']: self._check_string_fields(('name', 'type'), required=True, place=output_endpoint) self._check_string_fields(('label', 'description', 'friendcode'), place=output_endpoint) self._add_translation_index(output_endpoint['label'], type='outputendpoint', variable=output_endpoint['name'], field='label') self._add_translation_index(output_endpoint['description'], type='outputendpoint', variable=output_endpoint['name'], field='description') # Requirements self._check_array_fields(('requirements',))
def _parse_wiring_info(self): if self._info['type'] == 'mashup': self._info['wiring'] = get_wiring_skeleton() else: self._info['wiring'] = {} self._info['wiring']['inputs'] = [] self._info['wiring']['outputs'] = [] wiring_elements = self._xpath(WIRING_XPATH, self._doc) if len(wiring_elements) != 0: wiring_element = wiring_elements[0] for slot in self._xpath(INPUT_ENDPOINT_XPATH, wiring_element): self._add_translation_index(text_type(slot.get('label')), type='inputendpoint', variable=slot.get('name')) self._add_translation_index(text_type(slot.get('actionlabel', '')), type='inputendpoint', variable=slot.get('name')) self._add_translation_index(text_type(slot.get('description', '')), type='inputendpoint', variable=slot.get('name')) self._info['wiring']['inputs'].append({ 'name': text_type(slot.get('name')), 'type': text_type(slot.get('type')), 'label': text_type(slot.get('label', '')), 'description': text_type(slot.get('description', '')), 'actionlabel': text_type(slot.get('actionlabel', '')), 'friendcode': text_type(slot.get('friendcode', '')), }) for event in self._xpath(OUTPUT_ENDPOINT_XPATH, wiring_element): self._add_translation_index(text_type(event.get('label')), type='outputendpoint', variable=event.get('name')) self._add_translation_index(text_type(event.get('description', '')), type='outputendpoint', variable=event.get('name')) self._info['wiring']['outputs'].append({ 'name': text_type(event.get('name')), 'type': text_type(event.get('type')), 'label': text_type(event.get('label', '')), 'description': text_type(event.get('description', '')), 'friendcode': text_type(event.get('friendcode', '')), }) if self._info['type'] == "mashup": mashup_wiring_element = self.get_xpath(MASHUP_WIRING_XPATH, self._doc, required=False) if mashup_wiring_element is None: return self._info['wiring']['version'] = text_type(mashup_wiring_element.get('version', "1.0")) self._parse_wiring_connection_info(mashup_wiring_element) self._parse_wiring_operator_info(mashup_wiring_element) if self._info['wiring']['version'] == '1.0': # TODO: update to the new wiring format inputs = self._info['wiring']['inputs'] outputs = self._info['wiring']['outputs'] self._info['wiring'] = parse_wiring_old_version(self._info['wiring']) self._info['wiring']['inputs'] = inputs self._info['wiring']['outputs'] = outputs # END TODO elif self._info['wiring']['version'] == '2.0': visualdescription_element = self.get_xpath(VISUALDESCRIPTION_XPATH, mashup_wiring_element, required=False) if visualdescription_element is not None: self._parse_visualdescription_info(visualdescription_element) else: # TODO raise unsupported version exception pass
def _init(self): self._check_string_fields( ('title', 'description', 'longdescription', 'email', 'homepage', 'doc', 'changelog', 'image', 'smartphoneimage', 'license', 'licenseurl', 'issuetracker')) self._check_contacts_fields(('authors', 'contributors')) # Normalize/check preferences and properties (only for widgets and operators) if self._info['type'] != 'mashup': self._check_array_fields(('preferences', 'properties')) for preference in self._info['preferences']: self._check_string_fields(('name', 'type'), place=preference, required=True) self._check_string_fields(('label', 'description', 'default'), place=preference) self._check_boolean_fields(('readonly', 'secure'), place=preference, default=False) self._check_string_fields(('value', ), place=preference, null=True, default=None) for prop in self._info['properties']: self._check_string_fields(('name', 'type'), place=prop, required=True) self._check_string_fields(('label', 'description', 'default'), place=prop) self._check_boolean_fields(('secure', ), place=prop, default=False) if self._info['type'] == 'widget': self._check_array_fields(('altcontents', )) if self._info.get('contents', None) is None: raise TemplateParseException('Missing widget content info') if not isinstance(self._info['contents'], dict): raise TemplateParseException('Content info must be an object') self._check_contents_field(self._info['contents'], alternative=False) for altcontent in self._info['altcontents']: self._check_contents_field(altcontent) elif self._info['type'] == 'mashup': self._check_array_fields(('params', 'embedded')) for resource in self._info['embedded']: if isinstance(resource, dict): self._check_string_fields( ('vendor', 'name', 'version', 'src'), place=resource, required=True) else: raise TemplateParseException( 'embedded resource info must be an object') if 'wiring' not in self._info: self._info['wiring'] = get_wiring_skeleton() self._check_string_fields(('version', ), place=self._info['wiring'], default='1.0') if self._info['wiring']['version'] == '1.0': # TODO: update to the new wiring format inputs = self._info['wiring']['inputs'] outputs = self._info['wiring']['outputs'] self._info['wiring'] = parse_wiring_old_version( self._info['wiring']) self._info['wiring']['inputs'] = inputs self._info['wiring']['outputs'] = outputs # END TODO elif self._info['wiring']['version'] == '2.0': if 'visualdescription' not in self._info['wiring']: self._info['wiring']['visualdescription'] = {} self._check_array_fields( 'behaviours', place=self._info['wiring']['visualdescription'], required=False) self._check_behaviour_view_fields( self._info['wiring']['visualdescription']) for behaviour in self._info['wiring']['visualdescription'][ 'behaviours']: self._check_behaviour_view_fields(behaviour) if not 'wiring' in self._info: self._info['wiring'] = {} self._check_array_fields(('inputs', 'outputs'), place=self._info['wiring'], required=False) # Translations self._check_string_fields(('default_lang', ), default='en') self._info['translation_index_usage'] = {} if 'translations' not in self._info: self._info['translations'] = {} self._add_translation_index(self._info['title'], type='resource', field='title') self._add_translation_index(self._info['description'], type='resource', field='description') if self._info['type'] != 'mashup': for preference in self._info['preferences']: self._add_translation_index(preference['label'], type='vdef', variable=preference['name'], field='label') self._add_translation_index(preference['description'], type='vdef', variable=preference['name'], field='description') if preference['type'] == 'list': for option_index, option in enumerate( preference['options']): self._add_translation_index( option['label'], type='upo', variable=preference['name'], option=option_index) for prop in self._info['properties']: self._add_translation_index(prop['label'], type='vdef', variable=prop['name'], field='label') self._add_translation_index(prop['description'], type='vdef', variable=prop['name'], field='description') for input_endpoint in self._info['wiring']['inputs']: self._check_string_fields(('name', 'type'), required=True, place=input_endpoint) self._check_string_fields( ('label', 'description', 'actionlabel', 'friendcode'), place=input_endpoint) self._add_translation_index(input_endpoint['label'], type='inputendpoint', variable=input_endpoint['name'], field='label') self._add_translation_index(input_endpoint['description'], type='inputendpoint', variable=input_endpoint['name'], field='description') self._add_translation_index(input_endpoint['actionlabel'], type='inputendpoint', variable=input_endpoint['name'], field='actionlabel') for output_endpoint in self._info['wiring']['outputs']: self._check_string_fields(('name', 'type'), required=True, place=output_endpoint) self._check_string_fields( ('label', 'description', 'friendcode'), place=output_endpoint) self._add_translation_index(output_endpoint['label'], type='outputendpoint', variable=output_endpoint['name'], field='label') self._add_translation_index(output_endpoint['description'], type='outputendpoint', variable=output_endpoint['name'], field='description') # Requirements self._check_array_fields(('requirements', ))