def render_j2_template(config, template, data, locale_=None): """ render Jinja2 template :param config: dict of configuration :param template: template (relative path) :param data: dict of data :param locale_: the requested output Locale :returns: string of rendered template """ custom_templates = False try: templates_path = config['server']['templates']['path'] env = Environment(loader=FileSystemLoader(templates_path), extensions=['jinja2.ext.i18n', 'jinja2.ext.autoescape'], autoescape=select_autoescape(['html', 'xml'])) custom_templates = True LOGGER.debug('using custom templates: {}'.format(templates_path)) except (KeyError, TypeError): env = Environment(loader=FileSystemLoader(TEMPLATES), extensions=['jinja2.ext.i18n', 'jinja2.ext.autoescape'], autoescape=select_autoescape(['html', 'xml'])) LOGGER.debug('using default templates: {}'.format(TEMPLATES)) env.filters['to_json'] = to_json env.filters['format_datetime'] = format_datetime env.filters['format_duration'] = format_duration env.filters['human_size'] = human_size env.globals.update(to_json=to_json) env.filters['get_path_basename'] = get_path_basename env.globals.update(get_path_basename=get_path_basename) env.filters['get_breadcrumbs'] = get_breadcrumbs env.globals.update(get_breadcrumbs=get_breadcrumbs) env.filters['filter_dict_by_key_value'] = filter_dict_by_key_value env.globals.update(filter_dict_by_key_value=filter_dict_by_key_value) translations = Translations.load('locale', [locale_]) env.install_gettext_translations(translations) try: template = env.get_template(template) except TemplateNotFound as err: if custom_templates: LOGGER.debug(err) LOGGER.debug('Custom template not found; using default') env = Environment(loader=FileSystemLoader(TEMPLATES), extensions=['jinja2.ext.i18n']) template = env.get_template(template) else: raise return template.render(config=l10n.translate_struct(config, locale_, True), data=data, locale=locale_, version=__version__)
def test_translatedict(config, locale_): cfg = l10n.translate_struct(config, locale_, True) assert cfg['metadata']['identification'][ 'title'] == 'pygeoapi default instance' # noqa assert cfg['metadata']['identification']['keywords'] == [ 'geospatial', 'data', 'api' ] # noqa # test full equality (must come from cache) cfg2 = l10n.translate_struct(config, locale_, True) assert cfg is cfg2 # missing locale_ should return the same dict assert l10n.translate_struct(config, None) is config # noqa # missing or empty dict should return an empty dict assert l10n.translate_struct(None, locale_) == {} # noqa # test custom dict (translate from level 0, do not cache) test_dict = {'level0': {'en': 'test value', 'fr': 'valeur de test'}} tr_dict = l10n.translate_struct(test_dict, locale_) assert tr_dict['level0'] == 'test value' tr_dict2 = l10n.translate_struct(test_dict, locale_) assert tr_dict == tr_dict2 assert tr_dict is not tr_dict2 # test mixed structure test_input = [{ 'test': { 'en': 'test value', 'fr': 'valeur de test' } }, 'some string', { 'item1': 1 }, { 'item2a': [ 'list_item1', 'list_item2', { 'en': 'list value', 'fr': 'valeur de liste' } ], 'item2b': { 'en': 'test value', 'fr': 'valeur de test' } }] test_output = [{ 'test': 'test value' }, 'some string', { 'item1': 1 }, { 'item2a': ['list_item1', 'list_item2', 'list value'], 'item2b': 'test value' }] assert l10n.translate_struct(test_input, locale_) == test_output
def _to_geojson(self, json_obj, skip_geometry=False, single_feature=False): """ Turns a regular geoCore JSON object into GeoJSON. """ features = [] num_matched = None for item in json_obj.get('Items', []): feature = {'type': 'Feature', 'geometry': None} # Get ID and validate it id_ = item.pop('id', None) if id_ is None: LOGGER.warning(f'skipped record without ID') continue feature['id'] = id_ item['externalId'] = id_ # Pop 'total' value for numberMatched property (for paging) num_matched = int(item.pop('total', 0)) # Rename and set/fix date properties date_created = self._asisodate(item.get('created')) date_updated = self._asisodate(item.pop('published', None)) item['record-created'] = date_created item['record-updated'] = date_updated item['created'] = date_created item['updated'] = date_updated # Convert keywords to an array item['keywords'] = self._aslist(item.get('keywords')) # Get coordinates and set geometry and extent coords = self._getcoords(item) if coords: if skip_geometry: LOGGER.debug('skipped geometry') else: # Add Polygon geometry to feature feature['geometry'] = { 'type': 'Polygon', 'coordinates': coords } # Add extent object to feature item['extent'] = self._getextent( coords, item.pop('temporalExtent', None)) else: LOGGER.debug('record has no coordinates: ' 'cannot set geometry and extent') # Remove options and convert to associations options = item.pop('options', []) for opt in options: opt = l10n.translate_struct(opt, self.locale) url = opt.get('url') title = opt.get('name') type_ = opt.get('protocol') rel = 'item' i18n = self.locale desc = opt.get('description') if desc and desc.count(';') == 2: # TODO: retrieve mime type from URL or lookup rel, type_, i18n = desc.split(';') if not (type_ and url): # Do not add links without a type or URL continue lnk = { 'href': url, 'type': type_, 'rel': rel, 'title': title, 'hreflang': l10n.locale2str(i18n) if isinstance(i18n, l10n.Locale) else i18n } item.setdefault('associations', []).append(lnk) # Remove graphicOverview and promote/set first thumbnailUrl try: url = item.pop('graphicOverview')[0].get('overviewfilename') item['thumbnailUrl'] = url except (KeyError, IndexError, AttributeError): LOGGER.warning('could not find overview thumbnail') # Translate contacts, credits and distributors lists for prop in ('contact', 'credits', 'distributor'): values = item.get(prop, []) if values: item[prop] = l10n.translate_struct(values, self.locale) # Translate known concatenated "en; fr" values # TODO: add more props if needed, improve on geoCore side for prop in ('spatialRepresentation', 'type', 'status', 'maintenance', 'accessConstraints', 'characterSet'): values = [v.strip() for v in item.get(prop, '').split(';')] if len(values) != 2: continue item[prop] = values[0 if self.locale.language == 'en' else 1] # Set properties and add to feature list feature['properties'] = item features.append(feature) if features and single_feature == 1: LOGGER.debug('returning single feature') return features[0] LOGGER.debug('returning feature collection') collection = { 'type': 'FeatureCollection', 'features': features, 'numberReturned': len(features) } LOGGER.debug(f'provider said there are {num_matched} matches') if num_matched: collection['numberMatched'] = num_matched return collection