def _new_version_needed_and_not_forking(event: ISheetReferenceNewVersion)\ -> bool: """Check whether to autoupdate if resource is non-forkable. If the given resource is the last version or there's no last version yet, do autoupdate. If it's not the last version, but references the same object (namely the one which caused the autoupdate), don't update. If it's not the last version, but references a different object, throw an AutoUpdateNoForkAllowedError. This should only happen in batch requests. """ last = get_last_version(event.object, event.registry) if last is None or last is event.object: return True value = get_sheet_field(event.object, event.isheet, event.isheet_field, event.registry) last_value = get_sheet_field(last, event.isheet, event.isheet_field, event.registry) if last_value == value: return False else: raise AutoUpdateNoForkAllowedError(event.object, event)
def _new_version_needed_and_not_forking(event: ISheetReferenceNewVersion)\ -> bool: """Check whether to autoupdate if resource is non-forkable. If the given resource is the last version or there's no last version yet, do autoupdate. If it's not the last version, but references the same object (namely the one which caused the autoupdate), don't update. If it's not the last version, but references a different object, throw an AutoUpdateNoForkAllowedError. This should only happen in batch requests. """ last = _get_last_version(event.object, event.registry) if last is None or last is event.object: return True value = get_sheet_field(event.object, event.isheet, event.isheet_field, event.registry) last_value = get_sheet_field(last, event.isheet, event.isheet_field, event.registry) if last_value == value: return False else: raise AutoUpdateNoForkAllowedError(event.object, event)
def _get_old_versions(version: IVersionable) -> [IVersionable]: follows = get_sheet_field(version, IVersionable, 'follows') versions = [] while follows: old_version = follows[0] versions.append(old_version) follows = get_sheet_field(old_version, IVersionable, 'follows') return versions
def _get_sheet_field_from_subresource(sheet, sheet_field, sub_sheet_field, proposal): sub_resource = get_sheet_field(proposal, IMercatorSubResources, sheet_field) return get_sheet_field(sub_resource, sheet, sub_sheet_field)
def get_text_from_sheet(proposal, field, sheet): """Get text from sheetfields and return it. """ retrieved_field = get_sheet_field(proposal, IMercatorSubResources, field) field_text = get_sheet_field( retrieved_field, sheet, field).replace( ';', '') return field_text
def _append_user_data(user: IUser, row: [str], include_passwords: bool): name = get_sheet_field(user, IUserBasic, 'name') email = get_sheet_field(user, IUserExtended, 'email') creation_date = get_sheet_field(user, IMetadata, 'creation_date') creation_date_str = creation_date.strftime('%Y-%m-%d_%H:%M:%S') if include_passwords: passw = get_sheet_field(user, IPasswordAuthentication, 'password') else: passw = '' row.extend([name, email, creation_date_str, passw])
def validator(node, value): new_badge = node.get_value(value, child_node.name) new_badge_name = get_sheet_field(new_badge, IName, 'name') pool = find_service(context, 'badge_assignments') for badge_assignment in pool.values(): badge = get_sheet_field(badge_assignment, IBadgeAssignment, 'badge') badge_name = get_sheet_field(badge, IName, 'name') if new_badge_name == badge_name: raise colander.Invalid(child_node, 'Badge already assigned')
def index_location(resource, default) -> list: """Return search index keywords based on the "location_is_..." fields.""" location = get_sheet_field(resource, IMercatorSubResources, 'location') # TODO: Why is location '' in the first pass of that function # during MercatorProposal create? if location is None or location == '': return default locations = [] for keyword in LOCATION_INDEX_KEYWORDS: if get_sheet_field(location, ILocation, 'location_is_' + keyword): locations.append(keyword) return locations if locations else default
def index_requested_funding(resource: IResource, default) -> int: """Return search index keyword based on the "requested_funding" field.""" # TODO: Why is finance '' in the first pass of that function # during MercatorProposal create? # This sounds like a bug, the default value for References is None, finance = get_sheet_field(resource, IMercatorSubResources, 'finance') if finance is None or finance == '': return default funding = get_sheet_field(finance, IFinance, 'requested_funding') for limit in BUDGET_INDEX_LIMIT_KEYWORDS: if funding <= limit: return [limit] return default
def index_budget(resource: IResource, default) -> str: """Return search index keyword based on the "budget" field. The returned values are the same values as per the "requested_funding" field, or "above_50000" if the total budget value is more than 50,000 euro. """ finance = get_sheet_field(resource, IMercatorSubResources, 'finance') if finance is None or finance == '': return default funding = get_sheet_field(finance, IFinance, 'budget') for limit in BUDGET_INDEX_LIMIT_KEYWORDS: if funding <= limit: return [str(limit)] return ['above_50000']
def _fetch_all_districs(root: IResource) -> dict: pool = get_sheet(root, IPool) params = { 'depth': 3, 'interfaces': IMultiPolygon, } results = pool.get(params) bezirke = results['elements'] lookup = {} for bezirk in bezirke: if (get_sheet_field(bezirk, IMultiPolygon, 'administrative_division') == 'stadtbezirk'): name = (get_sheet_field(bezirk, IName, 'name')) lookup[name] = bezirk return lookup
def validator(node, value): new_badge = node.get_value(value, badge_ref.name) new_badge_name = get_sheet_field(new_badge, IName, 'name') new_object = node.get_value(value, object_ref.name) pool = find_service(context, 'badge_assignments') for badge_assignment in pool.values(): badge_sheet_values = get_sheet(badge_assignment, IBadgeAssignment).get() badge = badge_sheet_values['badge'] badge_name = get_sheet_field(badge, IName, 'name') obj = badge_sheet_values['object'] updating_current_assignment = context == badge_assignment if new_badge_name == badge_name \ and new_object == obj \ and not updating_current_assignment: raise colander.Invalid(badge_ref, 'Badge already assigned')
def post(self): """Create new resource and get response data. For :class:`adhocracy_core.interfaces.IItemVersion`: If a `new version` is already created in this transaction we don't want to create a new one. Instead we modify the existing one. This is needed to make :class:`adhocray_core.rest.batchview.BatchView` work. """ metric = self._get_post_metric_name() with statsd_timer(metric, rate=1, registry=self.registry): if is_batchmode(self.request) and self._creating_new_version(): last = get_sheet_field(self.context, ITags, 'LAST', registry=self.registry) if is_created_in_current_transaction(last, self.registry): self._update_version(last) resource = last else: resource = self._create() else: resource = self._create() cstruct = self.build_post_response(resource) return cstruct
def notify_policycompass(event): """Push comments of IExternalResource ressources to elastic search.""" comment = event.object external_resource = find_interface(comment, IExternalResource) if external_resource is None: return resource_name = get_sheet_field(external_resource, IName, 'name') match = re.match( '(?P<type>visualization|event|dataset|metric|model|indicator)' '_(?P<id>[0-9]+)', resource_name) # this is not a known policycompass external resource if match is None: return resource_type = match.group('type') resource_id = match.group('id') settings = event.registry.settings pcompass_endpoint = settings.get('adhocracy_pcompass.pcompass_endpoint', 'http://localhost:8000') url = '{base}/api/v1/searchmanager/updateindexitem/{res_type}/{res_id}' \ .format(base=pcompass_endpoint, res_type=resource_type, res_id=resource_id) r = requests.post(url) if r.status_code != 200: # indexing error on pcompass msg = 'Notifying policy compass about "{}_{}" failed with "{}"'.format( resource_type, resource_type, r.text) raise ValueError(msg)
def test_username_is_resolved_to_his_path(self, registry): from adhocracy_core.scripts import import_resources from .import_users import _get_user_locator (self._tempfd, filename) = mkstemp() with open(filename, 'w') as f: f.write(json.dumps([ {"path": "/principals/users/badge_assignments", "content_type": "adhocracy_core.resources.badge.IBadgeAssignment", "data": {"adhocracy_core.sheets.badge.IBadgeAssignment": {"subject": "user_by_login:god", "badge": "/orga/badges/badge0", "object": "/principals/users/0000000" }, "adhocracy_core.sheets.name.IName": {"name": "assign0"}} }])) root = registry.content.create(IRootPool.__identifier__) appstructs = {'adhocracy_core.sheets.name.IName': {'name': 'orga'}} orga = registry.content.create(IOrganisation.__identifier__, root, appstructs=appstructs, registry=registry) add_badges_service(orga, registry, {}) badge_appstructs = {'adhocracy_core.sheets.name.IName': {'name': 'badge0'}} registry.content.create(IBadge.__identifier__, orga['badges'], appstructs=badge_appstructs, registry=registry) import_resources(root, registry, filename) assignments = find_resource(root, '/principals/users/badge_assignments/') assignment = list(assignments.values())[0] subject = get_sheet_field(assignment, IBadgeAssignment, 'subject') user_locator = _get_user_locator(root, registry) god = user_locator.get_user_by_login('god') assert subject == god
def _get_creation_date(proposal): creation_date = get_sheet_field( proposal, IMetadata, 'item_creation_date') date = creation_date.date().strftime('%d.%m.%Y') return date
def _get_comments_count(self, resource): from adhocracy_core.utils import get_sheet_field from adhocracy_core.sheets.comment import ICommentable comments_count = get_sheet_field(resource, ICommentable, 'comments_count') return comments_count
def mercator2_index_location(resource, default) -> list: """Return search index keywords based on the location's fields.""" locations = [] if get_sheet_field(resource, sheets.mercator2.ILocation, 'is_online'): locations.append('online') if get_sheet_field(resource, sheets.mercator2.ILocation, 'has_link_to_ruhr'): locations.append('linked_to_ruhr') if get_sheet_field(resource, sheets.mercator2.ILocation, 'location') is not '': locations.append('specific') return locations if locations else default
def index_creator(resource, default) -> str: """Return creator userid value for the creator index.""" creator = get_sheet_field(resource, IMetadata, 'creator') if creator == '': # FIXME the default value should be None return creator userid = resource_path(creator) return userid
def evolve1_add_ititle_sheet_to_proposals(root): # pragma: no cover """Migrate title value from ole IIntroduction sheet to ITitle sheet.""" registry = get_current_registry() catalog = find_catalog(root, 'system') path = catalog['path'] interfaces = catalog['interfaces'] query = path.eq('/mercator') \ & interfaces.eq(IMercatorProposalVersion) \ & interfaces.noteq(ITitle) proposals = query.execute() catalogs = find_service(root, 'catalogs') for proposal in proposals: logger.info('updating {0}'.format(proposal)) introduction = get_sheet_field(proposal, IMercatorSubResources, 'introduction') if introduction == '' or introduction is None: continue alsoProvides(proposal, ITitle) catalogs.reindex_index(proposal, 'interfaces') sheet = registry.content.get_sheet(introduction, IIntroduction) if 'title' not in sheet.get().keys(): continue value = sheet.get()['title'] title = registry.content.get_sheet(proposal, ITitle) title.set({'title': value}) sheet.delete_field_values(['title'])
def index_workflow_state_of_item(resource, default) -> [str]: """Find item and return it`s value for the workflow_state index.""" item = find_interface(resource, IItem) try: state = get_sheet_field(item, IWorkflowAssignment, 'workflow_state') except (RuntimeConfigurationError, AttributeError): return default else: return state
def mercator2_index_requested_funding(resource: IResource, default) -> int: """Return search index keyword based on the "requested_funding" field.""" requested_funding = get_sheet_field(resource, sheets.mercator2.IFinancialPlanning, 'requested_funding') for limit in BUDGET_INDEX_LIMIT_KEYWORDS: if requested_funding <= limit: return [limit] return default
def _create_process(root, registry, organisation, district): name = get_sheet_field(district, IName, 'name') title = get_sheet_field(district, ITitle, 'title') appstructs = {IName.__identifier__: {'name': name}, ITitle.__identifier__: {'title': 'Kiezkasse für %s' % (title)}, ILocationReference.__identifier__: {'location': district} } registry.content.create(IProcess.__identifier__, parent=root['organisation'], appstructs=appstructs) transaction.commit()
def reset_password(self, password): """ Set `password` for creator user and delete itself.""" user = get_sheet_field(self, IMetadata, 'creator') password_sheet = get_sheet( user, adhocracy_core.sheets.principal.IPasswordAuthentication) password_sheet.set({'password': password}, send_event=False) if not user.active: # pragma: no cover user.activate() del self.__parent__[self.__name__]
def reindex_badge(event): """Reindex badge index if a backreference is modified/created.""" # TODO we cannot listen to the backreference modified event of the # IBadgeable sheet here, because this event is send before the # IBadgeAssignment fields 'subject' and 'badge' are properly stored. catalogs = find_service(event.object, 'catalogs') badgeable = get_sheet_field(event.object, IBadgeAssignment, 'object', registry=event.registry) catalogs.reindex_index(badgeable, 'badge')
def add_metadata(context: IAsset, registry: Registry, **kwargs): """Store asset file metadata and add `raw` download to `context`.""" file = get_sheet_field(context, IAssetData, 'data', registry=registry) meta_isheet = get_matching_isheet(context, IAssetMetadata) meta_sheet = get_sheet(context, meta_isheet, registry=registry) meta_appstruct = { 'size': file.size, 'filename': file.title, } meta_sheet.set(meta_appstruct, omit_readonly=False)
def _get_user_info(request: Request) -> (str, str): if not hasattr(request, 'authenticated_userid'): return ('', '') # ease scripting without user and testing user = get_user(request) if user is None: return ('', '') else: user_name = get_sheet_field(user, IUserBasic, 'name') user_path = resource_path(user) return (user_name, user_path)
def _update_badges_assignments(user: IUser, badges_names: [str], registry: Registry) -> None: _delete_badges_assignments(user) badges = _create_badges(user, badges_names, registry) normalized_badges_names = [_normalize_badge_name(b) for b in badges_names] badges_to_assign = [ b for b in badges if get_sheet_field(b, IName, 'name') in normalized_badges_names ] _assign_badges(user, badges_to_assign, registry)
def _update_badges_assignments(user: IUser, badges_names: [str], registry: Registry) -> None: _delete_badges_assignments(user) badges = _create_badges(user, badges_names, registry) normalized_badges_names = [_normalize_badge_name(b) for b in badges_names] badges_to_assign = [b for b in badges if get_sheet_field(b, IName, 'name') in normalized_badges_names] _assign_badges(user, badges_to_assign, registry)
def add_logbook_service_to_proposal_items(root): # pragma: no cover """Add logbook service to proposals.""" catalogs = find_service(root, 'catalogs') query = search_query._replace(interfaces=IMercatorProposal) proposals = catalogs.search(query).elements registry = get_current_registry(root) for proposal in proposals: if find_service(proposal, 'logbook') is None: logger.info('add logbook service to {0}'.format(proposal)) creator = get_sheet_field(proposal, IMetadata, 'creator') add_logbook_service(proposal, registry, {'creator': creator})
def mercator2_index_budget(resource: IResource, default) -> str: """Return search index keyword based on the "budget" field. The returned values are the same values as per the "requested_funding" field, or "above_50000" if the total budget value is more than 50,000 euro. """ budget = get_sheet_field(resource, sheets.mercator2.IFinancialPlanning, 'budget') for limit in BUDGET_INDEX_LIMIT_KEYWORDS: if budget <= limit: return [str(limit)] return ['above_50000']
def _get_rate_users(rateable: IRateable) -> set(IUser): params = {'depth': 3, 'interfaces': IRate, 'indexes': {'tag': 'LAST', 'rate': 1}, 'resolve': 'True', 'references': [(None, IRate, 'object', rateable)] } pool = get_sheet(rateable.__parent__, IPool) rates = pool.get(params)['elements'] users = [get_sheet_field(x, IRate, 'subject') for x in rates] return set(users)
def _fetch_district_by_name(root, district): pool = get_sheet(root, IPool) params = {'depth': 3, 'interfaces': IMultiPolygon, } results = pool.get(params) locations = results['elements'] for location in locations: if get_sheet_field(location, IName, 'name') == district: return location print('could not find district %s' % (district)) sys.exit()
def index_decision_date(context, default) -> datetime: """Return value for `decision_date` index.""" context = find_interface(context, IWorkflowAssignment) if context is None: return 'default' state_data = get_sheet_field(context, IWorkflowAssignment, 'state_data') datas = [x for x in state_data if x['name'] in ['result', 'selected', 'rejected']] if datas: decision_date = datas[0].get('start_date', default) return decision_date else: return default
def _get_rate_users(rateable: IRateable) -> set(IUser): params = { 'depth': 3, 'interfaces': IRate, 'indexes': { 'tag': 'LAST', 'rate': 1 }, 'resolve': 'True', 'references': [(None, IRate, 'object', rateable)] } pool = get_sheet(rateable.__parent__, IPool) rates = pool.get(params)['elements'] users = [get_sheet_field(x, IRate, 'subject') for x in rates] return set(users)
def test_create_and_create_and_assign_badge(self, context, registry, mock_messenger): from adhocracy_core import sheets registry.messenger = mock_messenger self._tempfd, filename = mkstemp() with open(filename, 'w') as f: f.write(json.dumps([ {'name': 'Alice', 'email': '*****@*****.**', 'initial-password': '', 'roles': [], 'groups': ['gods'], 'badges': ['Expert']}, {'name': 'Bob', 'email': '*****@*****.**', 'initial-password': '******', 'roles': [], 'groups': [], 'badges': ['Expert']}, ])) locator = self._get_user_locator(context, registry) self.call_fut(context, registry, filename) alice = locator.get_user_by_login('Alice') assignments = get_sheet_field(alice, sheets.badge.IBadgeable, 'assignments') assignment = assignments[0] assignment_sheet = get_sheet(assignment, sheets.badge.IBadgeAssignment) badge = context['principals']['badges']['expert'] assert assignment_sheet.get() == {'object': alice, 'badge': badge, 'subject': alice} bob = locator.get_user_by_login('Alice') assignments = get_sheet_field(bob, sheets.badge.IBadgeable, 'assignments') assignment = assignments[0] assignment_sheet = get_sheet(assignment, sheets.badge.IBadgeAssignment) badge = context['principals']['badges']['expert'] assert assignment_sheet.get() == {'object': bob, 'badge': badge, 'subject': bob} title = get_sheet_field(badge, sheets.title.ITitle, 'title') assert title == 'Expert'
def test_import_resources(self, registry, log): from adhocracy_core.scripts import import_resources (self._tempfd, filename) = mkstemp() with open(filename, 'w') as f: f.write(json.dumps([ {"path": "/", "content_type": "adhocracy_core.resources.organisation.IOrganisation", "data": {"adhocracy_core.sheets.name.IName": {"name": "alt-treptow"}}} ])) root = registry.content.create(IRootPool.__identifier__) import_resources(root, registry, filename) assert IOrganisation.providedBy(root['alt-treptow']) assert get_sheet_field(root['alt-treptow'], IName, 'name') == 'alt-treptow'
def _map_rating_users(rateables: [IRateable]) -> [(IRateable, set(IUser))]: rateables_users_map = [] for rateable in rateables: params = { 'depth': 3, 'interfaces': IRate, 'indexes': { 'tag': 'LAST', 'rate': 1 }, 'resolve': True, 'references': [(None, IRate, 'object', rateable)] } pool = get_sheet(rateable.__parent__, IPool) rates = pool.get(params)['elements'] users = [get_sheet_field(x, IRate, 'subject') for x in rates] rateables_users_map.append((rateable, set(users))) return rateables_users_map
def _get_rate_date(user: IUser, rateable: IRateable) -> str: pool = get_sheet(rateable.__parent__, IPool) params = { 'depth': 3, 'interfaces': IRate, 'indexes': { 'tag': 'LAST', 'rate': 1 }, 'references': [(None, IRate, 'subject', user), (None, IRate, 'object', rateable)], 'resolve': True } result = pool.get(params) rate = result['elements'][0] creation_date = get_sheet_field(rate, IMetadata, 'item_creation_date') creation_date_str = creation_date.strftime('%Y-%m-%d_%H:%M:%S') return creation_date_str
def _get_index_endpoint(context: IExternalResource, settings: dict) -> str: resource_name = get_sheet_field(context, IName, 'name') match = re.match( '(?P<type>visualization|event|dataset|metric|fuzzymap|indicator)' '_(?P<id>[0-9]+)', resource_name) if match is None: # pragma: no cover msg = 'This is not a known policy compass resource type' raise ValueError(msg) resource_type = match.group('type') resource_id = match.group('id') base_url = settings.get('adhocracy_pcompass.pcompass_endpoint', 'http://localhost:8000') endpoint = '{base}/api/v1/searchmanager/updateindexitem/{type}/{id_}'\ .format(base=base_url, type=resource_type, id_=resource_id) return endpoint
def test_add_example_process(pool_with_catalogs, registry): from adhocracy_core.utils import get_sheet_field from adhocracy_core.resources.organisation import IOrganisation from adhocracy_core.resources.geo import IMultiPolygon from adhocracy_core.resources.geo import add_locations_service import adhocracy_core.sheets.geo from adhocracy_meinberlin import resources from .root import add_example_process root = pool_with_catalogs add_locations_service(root, registry, {}) add_example_process(root, registry, {}) assert IOrganisation.providedBy(root['organisation']) kiezkasse = root['organisation']['kiezkasse'] assert resources.kiezkassen.IProcess.providedBy(kiezkasse) kiezregion = get_sheet_field(kiezkasse, adhocracy_core.sheets.geo.ILocationReference, 'location' ) assert IMultiPolygon.providedBy(kiezregion) bplan = root['organisation']['bplan'] assert resources.bplan.IProcess.providedBy(bplan)
def get_text_from_sheet(proposal, field, sheet): """Get text from sheetfields and return it.""" retrieved_field = get_sheet_field(proposal, IMercatorSubResources, field) field_text = get_sheet_field(retrieved_field, sheet, field) return normalize_text(field_text)
def export_proposals(): """Export all proposals from database and write them to csv file.""" doc = textwrap.dedent(inspect.getdoc(export_proposals)) parser = argparse.ArgumentParser(description=doc) parser.add_argument('config') args = parser.parse_args() env = bootstrap(args.config) root = env['root'] registry = env['registry'] catalogs = find_service(root, 'catalogs') query = search_query._replace( interfaces=IMercatorProposalVersion, sort_by='rates', reverse=True, indexes={'tag': 'LAST'}, resolve=True, ) proposals = catalogs.search(query).elements filename = create_filename(directory='./var/export', prefix='MercatorProposalExport', suffix='.csv') result_file = open(filename, 'w', newline='') wr = csv.writer(result_file, delimiter=';', quotechar='"', quoting=csv.QUOTE_MINIMAL) wr.writerow([ 'URL', 'Creation date', 'Title', 'Username', 'First name', 'Last name', 'Creator email', 'Creator country', 'Organisation status', 'Organisation name', 'Organisation country', 'Rates (Votes)', 'Number of Comments', 'Budget', 'Requested Funding', 'Other Funding', 'Granted?', 'Location Places', 'Location Online', 'Location Ruhr-Connection', 'Proposal Pitch', 'Description', 'How do you want to get there?', 'Story', 'Outcome', 'Value', 'Partners', 'Experience', 'Heard from' ]) for proposal in proposals: result = [] result.append(_get_proposal_url(proposal, registry)) # Creationdate creation_date = get_sheet_field(proposal, IMetadata, 'item_creation_date') date = creation_date.date().strftime('%d.%m.%Y') result.append(date) result.append(get_sheet_field(proposal, ITitle, 'title')) creator = get_sheet_field(proposal, IMetadata, 'creator') if creator is None: name = '' email = '' else: name = get_sheet_field(creator, IUserBasic, 'name') email = get_sheet_field(creator, IUserExtended, 'email') result.append(name) result.append(get_sheet_field(proposal, IUserInfo, 'personal_name')) result.append(get_sheet_field(proposal, IUserInfo, 'family_name')) result.append(email) result.append(get_sheet_field(proposal, IUserInfo, 'country')) # Organisation organization_info = get_sheet_field(proposal, IMercatorSubResources, 'organization_info') # status status = get_sheet_field(organization_info, IOrganizationInfo, 'status') result.append(status) # name result.append( get_sheet_field(organization_info, IOrganizationInfo, 'name')) # country if status == 'other': result.append('') else: organization_country = get_sheet_field(organization_info, IOrganizationInfo, 'country') result.append(organization_country) # Rates rates = index_rates(proposal, None) result.append(rates) # Comments comments = index_comments(proposal, None) result.append(comments) # requested funding finance = get_sheet_field(proposal, IMercatorSubResources, 'finance') budget = get_sheet_field(finance, IFinance, 'budget') result.append(str(budget)) requested_funding = get_sheet_field(finance, IFinance, 'requested_funding') result.append(str(requested_funding)) other_funding = get_sheet_field(finance, IFinance, 'other_sources') result.append(other_funding) if other_funding: granted = get_sheet_field(finance, IFinance, 'granted') else: granted = '' result.append(granted) location = get_sheet_field(proposal, IMercatorSubResources, 'location') # Location Places location_is_specific = get_sheet_field(location, ILocation, 'location_is_specific') locations = [] if location_is_specific: location1 = locations.append( get_sheet_field(location, ILocation, 'location_specific_1')) if location1: locations.append(location1) location2 = locations.append( get_sheet_field(location, ILocation, 'location_specific_2')) if location2: locations.append(location2) location3 = locations.append( get_sheet_field(location, ILocation, 'location_specific_3')) if location3: locations.append(location3) result.append(' '.join(locations)) is_online = get_sheet_field(location, ILocation, 'location_is_online') result.append(is_online) # Ruhr-Connection ruhr_connection = get_sheet_field(location, ILocation, 'location_is_linked_to_ruhr') result.append(ruhr_connection) # Proposal Pitch introduction = get_sheet_field(proposal, IMercatorSubResources, 'introduction') teaser = get_sheet_field(introduction, IIntroduction, 'teaser') result.append(teaser) result.append( get_text_from_sheet(proposal, 'description', IDescription)) result.append(get_text_from_sheet(proposal, 'steps', ISteps)) result.append(get_text_from_sheet(proposal, 'story', IStory)) result.append(get_text_from_sheet(proposal, 'outcome', IOutcome)) result.append(get_text_from_sheet(proposal, 'value', IValue)) result.append(get_text_from_sheet(proposal, 'partners', IPartners)) result.append(get_text_from_sheet(proposal, 'experience', IExperience)) # Heard from heard_from = get_sheet(proposal, IHeardFrom) result.append(get_heard_from_text(heard_from.get())) wr.writerow(result) env['closer']() print('Exported mercator proposals to %s' % filename)