def rel_datetime_format(dt, fmt=None, relative=False): """Template filter for readable formatting of datetime.datetime""" if relative: time = dates.format_timedelta(datetime.utcnow() - dt, locale=get_locale()) return gettext('{time} ago').format(time=time) else: fmt = fmt or 'MMM dd, yyyy hh:mm a' return dates.format_datetime(dt, fmt, locale=get_locale())
def test_force_locale(self): app = flask.Flask(__name__) b = babel.Babel(app) @b.localeselector def select_locale(): return 'de_DE' with app.test_request_context(): assert str(babel.get_locale()) == 'de_DE' with babel.force_locale('en_US'): assert str(babel.get_locale()) == 'en_US' assert str(babel.get_locale()) == 'de_DE'
def test_set_locale(self): en = Locale('en') fr = Locale('fr') with self.app.test_request_context('/'): assert get_locale() == en with i18n.set_locale('fr') as new_locale: assert get_locale() == fr assert isinstance(new_locale, Locale) assert new_locale == fr assert get_locale() == en with i18n.set_locale(fr): assert get_locale() == fr with i18n.set_locale(en): assert get_locale() == en assert get_locale() == fr assert get_locale() == en # no request context: no locale set app_ctx = _app_ctx_stack.top self._ctx.pop() self._ctx = None app_ctx.push() with i18n.set_locale(fr): assert get_locale() is None
def __call__(self, field, **kwargs): kwargs.setdefault('id', field.id) field_id = kwargs.pop('id') value = kwargs.pop('value', None) if value is None: value = field._value() if not value: value = '' time_fmt = get_locale().time_formats['short'].format is_h12 = ('%(h)s' in time_fmt or '%(K)s' in time_fmt) input_params = { 'data-template': self.widget_mode, 'data-show-meridian': is_h12, 'data-minute-step': self.minuteStep, 'data-show-seconds': self.showSeconds, 'data-second-step': self.secondStep, 'data-show-inputs': self.showInputs, 'data-disable-focus': self.disableFocus, 'data-modal-backdrop': self.modalBackdrop } input_params = {k: Markup(json.dumps(v)) for k, v in input_params.items()} return Markup(render_template(self.template, id=field_id, value=value, field=field, required=False, timepicker_attributes=input_params))
def process_formdata(self, valuelist): if valuelist: date_str = ' '.join(valuelist) locale = get_locale() date_fmt = locale.date_formats['short'] date_fmt = babel2datetime(date_fmt) date_fmt = date_fmt.replace('%B', '%m')\ .replace('%b', '%m') # force numerical months time_fmt = locale.time_formats['short'] time_fmt = babel2datetime(time_fmt) datetime_fmt = u'{} | {}'.format(date_fmt, time_fmt) try: self.data = datetime.datetime.strptime(date_str, datetime_fmt) if not self.use_naive: tz = get_timezone() if self.data.tzinfo: self.data = self.data.astimezone(tz) else: self.data = tz.localize(self.data) # convert to UTC self.data = utc_dt(self.data) except ValueError: self.data = None raise ValueError(self.gettext('Not a valid datetime value'))
def process_formdata(self, valuelist): if valuelist: date_str = " ".join(valuelist) locale = get_locale() date_fmt = locale.date_formats["short"] date_fmt = babel2datetime(date_fmt) date_fmt = date_fmt.replace("%B", "%m").replace( "%b", "%m" ) # force numerical months time_fmt = locale.time_formats["short"] time_fmt = babel2datetime(time_fmt) datetime_fmt = f"{date_fmt} | {time_fmt}" try: self.data = datetime.datetime.strptime(date_str, datetime_fmt) if not self.use_naive: tz = get_timezone() if self.data.tzinfo: self.data = self.data.astimezone(tz) else: self.data = tz.localize(self.data) # convert to UTC self.data = utc_dt(self.data) except ValueError: self.data = None raise ValueError(self.gettext("Not a valid datetime value"))
def _get_translations(): ctx = _request_ctx_stack.top root = os.path.dirname(os.path.abspath(__file__)) translations_path = os.path.join(root, 'translations') translations = support.Translations.load( translations_path, [flask_babel.get_locale()], domain='messages' ) ctx.wtforms_translations = translations return translations
def datetimeformat(eval_ctx, value, kind='LONG_DATETIME'): language_formats = config.LANGUAGES_FORMATS or {} language = str(get_locale()) format = 'dd/MM/yyyy HH:mm' if language in language_formats: format = language_formats[language][kind] if kind in language_formats[language] else format return format_datetime(value, format)
def common_bootsrap_payload(self): """Common data always sent to the client""" messages = get_flashed_messages(with_categories=True) locale = str(get_locale()) return { 'flash_messages': messages, 'conf': {k: conf.get(k) for k in FRONTEND_CONF_KEYS}, 'locale': locale, 'language_pack': get_language_pack(locale), }
def recommendations(page_name): language_code = get_locale().language page = Page.query.filter(Page.name==page_name, Page.language_code==language_code).first() if not page: page = Page.query.filter(Page.name==page_name, Page.language_code=='en').first() if not page: return render_template('errors/404.html'), 404 return render_template('help_pages.html', page=page)
def __call__(self, field, **kwargs): kwargs.setdefault('id', field.id) field_id = kwargs.pop('id') kwargs.setdefault('name', field.name) field_name = kwargs.pop('name') locale = get_locale() date_fmt = locale.date_formats['short'].pattern date_fmt = babel2datetime(date_fmt) date_fmt = date_fmt.replace('%B', '%m').replace('%b', '%m') # force numerical months time_fmt = u'%H:%M' datetime_fmt = '{} | {}'.format(date_fmt, time_fmt) value = kwargs.pop('value', None) if value is None: if field.data: value = field.data date_value = value.strftime(date_fmt) if value else u'' time_value = value.strftime(time_fmt) if value else u'' elif field.raw_data: value = field.raw_data # example "10/10/16 | 09:00" value = u''.join(value) value = value.split(u'|') try: date_value = datetime.strptime(value[0].strip(), date_fmt) except (ValueError, IndexError): date_value = u'' try: time_value = value[1].strip() # example "09:00" except IndexError: time_value = u'' else: date_value = u'' time_value = u'' return ( Markup( u'<div class="form-inline">\n' u'<input class="datetimepicker" type="hidden" id="{id}" name="{id}" ' u'value="{date} | {time}" />\n' u''.format(id=field_id, name=field_name, date=date_value, time=time_value)) + self.date(field, id=field_id + '-date', name=field_name + '-date', value=date_value) + self.time(field, id=field_id + '-time', name=field_name + '-time', value=time_value) + Markup(u'</div>') )
def setup_request(): """Set some request attributes at the beginning of the request. By default, caching will be disabled.""" request._begin_time = time.time() request._app_locale = str(get_locale()) request.session_id = request.headers.get('X-Aleph-Session') request._http_cache = False request._http_private = False request._http_revalidate = False request._http_etag = None request._log_tags = {}
def translate(original, language_code=''): if language_code == '': language_code = get_locale().language translation = Translation.query.filter( Translation.original==original, Translation.language_code==language_code, ).first() if translation: return translation.translated else: return original
def _extend_global_variable() -> None: """ Extend the global variable ``g`` with further information: * ``g.locale``: The current locale (e.g. ``en-US`` or ``de``). * ``g.title``: The app title. * ``g.user``: The user object. """ g.locale = get_locale() g.title = BaseConfiguration.TITLE_SHORT g.user = current_user
def utility_processor(): # Send the current date & time today = datetime.date.today() language = get_locale() return dict( pag=PaginationHelper.pag, today=today, config=config, language=str(language), site_name=config.SITE_NAME)
def format_transcribed_by(item): locale = flask_babel.get_locale() if locale.language == "ru": format_name = utils.make_genitive else: format_name = unidecode.unidecode transcriber = item.get("transcriber") if transcriber is None: return "" else: return ", ".join(map(format_name, transcriber))
def title(self): current_locale = get_locale() if current_locale is None: current_locale = babel.Locale('en') # Special case possesive form in English if current_locale.language.lower() == 'en' and \ current_user.name[:-1] == u's': return u"{}' Requests".format(current_user.name) else: # TRANS: The title of the page listing all requests an individual # TRANS: user has made. return gettext(u"%(name)s's Requests", name=current_user.name)
def locale_preferences(): main_locale = get_locale() locales = [main_locale] def to_locale(language): try: return Locale(language) except UnknownLocaleError: return main_locale locales.extend(imap(to_locale, request.accept_languages.itervalues())) return locales
def _value(self): if self.raw_data: return ' '.join(self.raw_data) else: date_fmt = get_locale().date_formats['short'].pattern # force numerical months and 4 digit years date_fmt = date_fmt.replace('MMMM', 'MM')\ .replace('MMM', 'MM')\ .replace('yyyy', 'y')\ .replace('yy', 'y')\ .replace('y', 'yyyy') return format_date(self.data, date_fmt) if self.data else ''
def myget_translations(): """Returns the correct gettext translations that should be used for this request. This will never fail and return a dummy translation object if used outside of the request or if a translation cannot be found. """ ctx = _request_ctx_stack.top if ctx is None: return None translations = getattr(ctx, 'babel_translations', None) dirname = os.path.join(ctx.app.root_path, ctx.app.config.get('LANGUAGE_DIR')) # base translations files = [] if os.path.exists(dirname): try: for mo in [f[:-3] for f in os.listdir(os.path.join(dirname, str(get_locale()) + '/LC_MESSAGES')) if f.endswith('.mo')]: files.append(support.Translations.load(dirname, [get_locale()], domain=mo)) except: pass # load translations of blueprints for bp_name in ctx.app.blueprints: dirname = os.path.join(ctx.app.blueprints[bp_name].root_path, 'translations') if not os.path.exists(dirname): continue files.append(support.Translations.load(dirname, [get_locale()], domain=bp_name)) for f in files: if not translations: translations = f else: try: if f.files[0] not in translations.files: translations.files.extend(f.files) translations._catalog.update(f._catalog) except: pass ctx.babel_translations = translations return translations
def age(dt, now=None, add_direction=True, date_threshold=None): """ :param dt: :class:`datetime<datetime.datetime>` instance to format :param now: :class:`datetime<datetime.datetime>` instance to compare to `dt` :param add_direction: if `True`, will add "in" or "ago" (example for `en` locale) to time difference `dt - now`, i.e "in 9 min." or " 9min. ago" :param date_threshold: above threshold, will use a formated date instead of elapsed time indication. Supported values: "day". """ # Fail silently for now XXX if not dt: return "" if not now: now = datetime.datetime.utcnow() locale = babel.get_locale() dt = utc_dt(dt) now = utc_dt(now) delta = dt - now if date_threshold is not None: dy, dw, dd = dt_cal = dt.isocalendar() ny, nw, nd = now_cal = now.isocalendar() if dt_cal != now_cal: # not same day remove_year = dy == ny date_fmt = locale.date_formats["long"].pattern time_fmt = locale.time_formats["short"].pattern fmt = locale.datetime_formats["medium"] if remove_year: date_fmt = date_fmt.replace("y", "").strip() # remove leading or trailing spaces, comma, etc... date_fmt = re.sub("^[^A-Za-z]*|[^A-Za-z]*$", "", date_fmt) fmt = fmt.format(time_fmt, date_fmt) return babel.format_datetime(dt, format=fmt) # don't use (flask.ext.)babel.format_timedelta: as of Flask-Babel 0.9 it # doesn't support "threshold" arg. return format_timedelta( delta, locale=locale, granularity="minute", threshold=0.9, add_direction=add_direction, )
def get_article(article_id, parse=False): locale = get_locale() contr = ArticleController(current_user.id) article = contr.get(id=article_id) if not article.readed: article['readed'] = True contr.update({'id': article_id}, {'readed': True}) article['category_id'] = article.category_id or 0 feed = FeedController(current_user.id).get(id=article.feed_id) article['icon_url'] = url_for('icon.icon', url=feed.icon_url) \ if feed.icon_url else None article['date'] = format_datetime(localize(article.date), locale=locale) return article
def _value(self): if self.raw_data: return " ".join(self.raw_data) else: date_fmt = get_locale().date_formats["short"].pattern # force numerical months and 4 digit years date_fmt = ( date_fmt.replace("MMMM", "MM") .replace("MMM", "MM") .replace("yyyy", "y") .replace("yy", "y") .replace("y", "yyyy") ) return format_date(self.data, date_fmt) if self.data else ""
def create_project(): form = ProjectForm() if request.method == "GET" and 'project_id' in request.values: form.name.data = request.values['project_id'] if request.method == "POST": # At first, we don't want the user to bother with the identifier # so it will automatically be missing because not displayed into # the form # Thus we fill it with the same value as the filled name, # the validation will take care of the slug if not form.id.data: form.id.data = form.name.data if form.validate(): # save the object in the db project = form.save() db.session.add(project) db.session.commit() # create the session object (authenticate) session[project.id] = True session.update() # send reminder email g.project = project message_title = _("You have just created '%(project)s' " "to share your expenses", project=g.project.name) message_body = render_template("reminder_mail.%s.j2" % get_locale().language) msg = Message(message_title, body=message_body, recipients=[project.contact_email]) try: current_app.mail.send(msg) except SMTPRecipientsRefused: msg_compl = 'Problem sending mail. ' # TODO: destroy the project and cancel instead? else: msg_compl = '' # redirect the user to the next step (invite) flash(_("%(msg_compl)sThe project identifier is %(project)s", msg_compl=msg_compl, project=project.id)) return redirect(url_for(".list_bills", project_id=project.id)) return render_template("create_project.html", form=form)
def inject(): from dudel.views import get_locale from dudel.models import Poll return dict( ICONS=ICONS, login_form=LoginForm(), lang_form=LanguageForm(), enumerate=enumerate, lang=get_locale(), current_timezone=get_current_timezone(), default_timezone=default_timezone, PollType=PollType, cx=cx )
def process_formdata(self, valuelist): valuelist = [i for i in valuelist if i.strip()] if valuelist: date_str = ' '.join(valuelist) date_fmt = get_locale().date_formats['short'] date_fmt = babel2datetime(date_fmt) date_fmt = date_fmt.replace('%B', '%m')\ .replace('%b', '%m') try: self.data = datetime.datetime.strptime(date_str, date_fmt).date() except ValueError: self.data = None raise ValueError(self.gettext('Not a valid datetime value'))
def localization_js(): global _localization_cache locale=repr(get_locale()) if _localization_cache.get(locale,None) is None: data = render_template(os.path.join('js/localization.js'), N_=N_, nN_=nN_) _localization_cache[locale] = (data, sha1(repr(data)).hexdigest()) data,datahash = _localization_cache[locale] if request.environ.get('HTTP_IF_NONE_MATCH', None) == datahash: response = make_response('',304) else: response = make_response(data) response.headers['Content-Type'] = 'text/javascript; charset=utf-8' response.headers['Etag']=datahash return response
def fixed_get_translations(): """Returns the correct gettext translations that should be used for this request. This will never fail and return a dummy translation object if used outside of the request or if a translation cannot be found. """ ctx = _request_ctx_stack.top if ctx is None: return None translations = getattr(ctx, 'babel_translations', None) if translations is None: locale = flask_babel.get_locale() translations = support.Translations() if str(locale) != default_locale: # plugin translations plugins = octoprint.plugin.plugin_manager().enabled_plugins for name, plugin in plugins.items(): dirs = map(lambda x: os.path.join(x, "_plugins", name), additional_folders) + [os.path.join(plugin.location, 'translations')] for dirname in dirs: if not os.path.isdir(dirname): continue try: plugin_translations = support.Translations.load(dirname, [locale]) except: logger.exception("Error while trying to load translations for plugin {name}".format(**locals())) else: if isinstance(plugin_translations, support.Translations): translations = translations.merge(plugin_translations) logger.debug("Using translation plugin folder {dirname} from plugin {name} for locale {locale}".format(**locals())) break else: logger.debug("No translations for locale {locale} from plugin {name}".format(**locals())) # core translations dirs = additional_folders + [os.path.join(ctx.app.root_path, 'translations')] for dirname in dirs: core_translations = support.Translations.load(dirname, [locale]) if isinstance(core_translations, support.Translations): logger.debug("Using translation core folder {dirname} for locale {locale}".format(**locals())) break else: logger.debug("No translations for locale {} in core folders".format(locale)) translations = translations.merge(core_translations) ctx.babel_translations = translations return translations
def _get_translations(): """Returns the correct gettext translations. Copy from flask-babel with some modifications. """ ctx = _request_ctx_stack.top if ctx is None: return None # babel should be in extensions for get_locale if "babel" not in ctx.app.extensions: return None translations = getattr(ctx, "wtforms_translations", None) if translations is None: dirname = messages_path() translations = support.Translations.load(dirname, [get_locale()], domain="wtforms") ctx.wtforms_translations = translations return translations
def test_get_template_i18n(self): template_path = '/myfile.txt' en = Locale('en') result = i18n.get_template_i18n(template_path, locale=en) self.assertIn('/myfile.en.txt', result) self.assertIn('/myfile.txt', result) en = Locale('en_US') result = i18n.get_template_i18n(template_path, locale=en) self.assertIn('/myfile.en_US.txt', result) self.assertIn('/myfile.txt', result) with i18n.set_locale('fr'): result = i18n.get_template_i18n(template_path, get_locale()) self.assertIn('/myfile.fr.txt', result) self.assertIn('/myfile.txt', result)
def before_request(): if current_user.is_authenticated: current_user.last_seen = datetime.utcnow() db.session.commit() g.locale = str( get_locale()) # converted to string as Babel returns locale object
def lang(): return str(get_locale())
def format_number(value): if value or value == 0: return numbers.format_decimal(value, locale=flask_babel.get_locale()) return ""
def before_request(): """Set user last seen time user.""" if current_user.is_authenticated: g.search_form = SearchForm() g.locale = str(get_locale())
async def evaluate_locale(): request.locale = get_locale()
def search(): """View the results of a search.""" start_time = time.process_time() if current_app.config['KERKO_USE_TRANSLATIONS']: babel_domain.as_default() criteria = Criteria(request) form = SearchForm(csrf_enabled=False) if form.validate_on_submit(): url = criteria.build_add_keywords_url( scope=form.scope.data, value=form.keywords.data) return redirect(url, 302) base_filter_terms = query.build_filter_terms('item_type', exclude=['note', 'attachment']) search_results, facet_results, total_count, page_count, last_sync = query.run_query( criteria, query.get_search_return_fields(criteria.page_len), default_terms=base_filter_terms, ) if criteria.page_len == 1 and criteria.id and ( total_count == 0 or criteria.id != search_results[0]['id'] ): # The search result page no longer points to the desired item. return redirect(url_for('.item_view', item_id=criteria.id, _external=True), 301) criteria.fit_pager(page_count) breadbox = build_breadbox(criteria, facet_results) pager_sections = get_pager_sections(criteria.page_num, page_count) context = { 'facet_results': facet_results, 'breadbox': breadbox, 'active_facets': breadbox['filters'].keys() if 'filters' in breadbox else [], 'sorter': build_sorter(criteria), 'total_count': total_count, 'total_count_formatted': format_number(total_count, locale=get_locale()), 'page_count': page_count, 'page_count_formatted': format_number(page_count, locale=get_locale()), 'page_len': criteria.page_len, 'show_abstracts': criteria.show_abstracts, 'abstracts_toggler_url': criteria.build_url( show_abstracts=not criteria.show_abstracts, page_num=criteria.page_num ), 'is_searching': criteria.has_keyword_search() or criteria.has_filter_search(), 'locale': get_locale(), 'last_sync': datetime.fromtimestamp( last_sync, tz=datetime.now().astimezone().tzinfo ) if last_sync else None, } if criteria.page_len == 1 and total_count != 0: # Retrieve item ids corresponding to individual result page numbers. page_kwargs = {} page_criteria = copy.deepcopy(criteria) for page_num in get_page_numbers(pager_sections): if page_num == criteria.page_num: # We already know the current page's item id. No further query necessary. page_kwargs[page_num] = {'id_': search_results[0]['id']} else: # Run a search query to get the item id corresponding to the page number. page_criteria.page_num = page_num page_search_results, _, _, _, _ = query.run_query( page_criteria, return_fields=['id'], query_facets=False, default_terms=base_filter_terms, ) if page_search_results: page_kwargs[page_num] = {'id_': page_search_results[0]['id']} context['pager'] = build_pager(pager_sections, criteria, page_kwargs) list_page_num = int((criteria.page_num - 1) / current_app.config['KERKO_PAGE_LEN'] + 1) query.build_creators_display(search_results[0]) query.build_item_facet_results(search_results[0]) query.build_relations( search_results[0], query.get_search_return_fields(page_len=None, exclude=['coins']), sort=current_app.config['KERKO_RELATIONS_SORT'], default_terms=base_filter_terms, ) if context['is_searching']: context['search_title'] = gettext('Your search') else: context['search_title'] = gettext('Full bibliography') return render_template( current_app.config['KERKO_TEMPLATE_SEARCH_ITEM'], title=search_results[0].get('data', {}).get('title', ''), item=search_results[0], item_url=url_for( '.item_view', item_id=search_results[0]['id'], _external=True ) if search_results[0] else '', back_url=criteria.build_url(page_num=list_page_num), time=time.process_time() - start_time, **context ) if total_count > 0: context['pager'] = build_pager(pager_sections, criteria) search_results_urls = [ criteria.build_url( page_num=(criteria.page_num - 1) * (criteria.page_len or 0) + i + 1, page_len=1, id_=result['id'], ) for i, result in enumerate(search_results) ] search_results = zip(search_results, search_results_urls) if context['is_searching']: context['title'] = ngettext('Result', 'Results', total_count) else: context['title'] = gettext('Full bibliography') else: context['title'] = gettext('Your search did not match any resources') return render_template( current_app.config['KERKO_TEMPLATE_SEARCH'], form=form, search_results=search_results, print_url=criteria.build_url(page_len='all', print_preview=True), print_preview=criteria.print_preview, download_urls={ key: criteria.build_download_url(key) for key in current_app.config['KERKO_COMPOSER'].citation_formats.keys() }, time=time.process_time() - start_time, **context )
def get_month_selection_field(validate_with): month_names = get_month_names(locale=get_locale()) month_choices = [('', _('Select month'))] + [(str(key), month_names[key]) for key in range(1, 13)] return SelectField(choices=month_choices, default='', validators=validate_with)
def create(): entity_id, entity_type = None, None for entity_type in ENTITY_TYPES: entity_id = request.args.get(entity_type) if entity_id: entity_type = entity_type break if not (entity_id or entity_type): logging.warning("Unsupported entity type") raise BadRequest("Unsupported entity type") if not entity_id: flash.info(gettext("Please choose an entity to review.")) return redirect(url_for('search.selector', next=url_for('.create'))) if current_user.is_blocked: flash.error( gettext("You are not allowed to write new reviews because your " "account has been blocked by a moderator.")) return redirect(url_for('user.reviews', user_id=current_user.id)) # Checking if the user already wrote a review for this entity reviews, count = db_review.list_reviews(user_id=current_user.id, entity_id=entity_id) review = reviews[0] if count is not 0 else None if review: flash.error( gettext("You have already published a review for this entity!")) return redirect(url_for('review.entity', id=review["id"])) if current_user.is_review_limit_exceeded: flash.error( gettext("You have exceeded your limit of reviews per day.")) return redirect(url_for('user.reviews', user_id=current_user.id)) form = ReviewCreateForm(default_license_id=current_user.license_choice, default_language=get_locale()) if form.validate_on_submit(): is_draft = form.state.data == 'draft' if form.text.data == '': form.text.data = None review = db_review.create(user_id=current_user.id, entity_id=entity_id, entity_type=entity_type, text=form.text.data, rating=form.rating.data, license_id=form.license_choice.data, language=form.language.data, is_draft=is_draft) if form.remember_license.data: db_users.update(current_user.id, user_new_info={ "license_choice": form.license_choice.data, }) if is_draft: flash.success(gettext("Review has been saved!")) else: flash.success(gettext("Review has been published!")) return redirect(url_for('.entity', id=review['id'])) entity = get_entity_by_id(entity_id, entity_type) if not entity: flash.error( gettext( "You can only write a review for an entity that exists on MusicBrainz!" )) return redirect(url_for('search.selector', next=url_for('.create'))) if entity_type == 'release_group': spotify_mappings = mbspotify.mappings(entity_id) soundcloud_url = soundcloud.get_url(entity_id) if not form.errors: flash.info( gettext( "Please provide some text or a rating for this review.")) return render_template('review/modify/write.html', form=form, entity_type=entity_type, entity=entity, spotify_mappings=spotify_mappings, soundcloud_url=soundcloud_url) if not form.errors: flash.info( gettext("Please provide some text or a rating for this review.")) return render_template('review/modify/write.html', form=form, entity_type=entity_type, entity=entity)
def create_app(debug=None, config_path=None): app = CustomFlask( import_name=__name__, use_flask_uuid=True, ) # Configuration files app.config.from_pyfile(os.path.join( os.path.dirname(os.path.realpath(__file__)), '..', '..', 'default_config.py' )) config_file = os.path.join( os.path.dirname(os.path.realpath(__file__)), '..', '..', 'consul_config.py' ) if deploy_env: print("Checking if consul template generated config file exists: {}".format(config_file)) for _ in range(CONSUL_CONFIG_FILE_RETRY_COUNT): if not os.path.exists(config_file): sleep(1) if not os.path.exists(config_file): print("No configuration file generated yet. Retried {} times, exiting.".format(CONSUL_CONFIG_FILE_RETRY_COUNT)) sys.exit(-1) print("Loading consul config file {}".format(config_file)) app.config.from_pyfile(config_file, silent=True) app.config.from_pyfile(os.path.join( os.path.dirname(os.path.realpath(__file__)), '..', '..', 'custom_config.py' ), silent=True) if config_path: app.config.from_pyfile(config_path) if debug is not None: app.debug = debug if app.debug and app.config['SECRET_KEY']: app.init_debug_toolbar() # Error handling from critiquebrainz.frontend.error_handlers import init_error_handlers init_error_handlers(app) # Static files from critiquebrainz.frontend import static_manager static_manager.read_manifest() app.init_loggers( file_config=app.config.get("LOG_FILE"), email_config=app.config.get("LOG_EMAIL"), sentry_config=app.config.get("LOG_SENTRY"), ) # CritiqueBrainz Database from critiquebrainz import db as critiquebrainz_db critiquebrainz_db.init_db_engine(app.config.get("SQLALCHEMY_DATABASE_URI")) add_robots(app) # MusicBrainz Database from brainzutils import musicbrainz_db musicbrainz_db.init_db_engine(app.config.get("MB_DATABASE_URI")) # Redis (cache) from brainzutils import cache if "REDIS_HOST" in app.config and \ "REDIS_PORT" in app.config and \ "REDIS_NAMESPACE" in app.config: cache.init( host=app.config["REDIS_HOST"], port=app.config["REDIS_PORT"], namespace=app.config["REDIS_NAMESPACE"], ) else: logging.warning("Redis is not defined in config file. Skipping initialization.") from critiquebrainz.frontend import babel babel.init_app(app) from critiquebrainz.frontend import login login.login_manager.init_app(app) from critiquebrainz.frontend.login.provider import MusicBrainzAuthentication login.mb_auth = MusicBrainzAuthentication( name='musicbrainz', client_id=app.config['MUSICBRAINZ_CLIENT_ID'], client_secret=app.config['MUSICBRAINZ_CLIENT_SECRET'], authorize_url="https://musicbrainz.org/oauth2/authorize", access_token_url="https://musicbrainz.org/oauth2/token", base_url="https://musicbrainz.org/", ) # APIs from critiquebrainz.frontend.external import mbspotify mbspotify.init(app.config['MBSPOTIFY_BASE_URI'], app.config['MBSPOTIFY_ACCESS_KEY']) from critiquebrainz.frontend.external import musicbrainz musicbrainz.init( app_name=app.config['MUSICBRAINZ_USERAGENT'] or "CritiqueBrainz Custom", app_version="1.0", hostname=app.config['MUSICBRAINZ_HOSTNAME'] or "musicbrainz.org", ) # Template utilities # TODO (code-master5): disabled no-member warnings just as a workaround to deal with failing tests till the # issue [https://github.com/PyCQA/pylint/issues/2563] with pylint is resolved app.jinja_env.add_extension('jinja2.ext.do') from critiquebrainz.utils import reformat_date, reformat_datetime, track_length, track_length_ms, parameterize from critiquebrainz.frontend.external.musicbrainz_db.entities import get_entity_by_id app.jinja_env.filters['date'] = reformat_date app.jinja_env.filters['datetime'] = reformat_datetime app.jinja_env.filters['track_length'] = track_length app.jinja_env.filters['track_length_ms'] = track_length_ms app.jinja_env.filters['parameterize'] = parameterize app.jinja_env.filters['entity_details'] = get_entity_by_id from flask_babel import Locale, get_locale app.jinja_env.filters['language_name'] = lambda language_code: Locale(language_code).get_language_name(get_locale()) app.context_processor(lambda: dict(get_static_path=static_manager.get_static_path)) # Blueprints from critiquebrainz.frontend.views.index import frontend_bp from critiquebrainz.frontend.views.review import review_bp from critiquebrainz.frontend.views.search import search_bp from critiquebrainz.frontend.views.artist import artist_bp from critiquebrainz.frontend.views.label import label_bp from critiquebrainz.frontend.views.release_group import release_group_bp from critiquebrainz.frontend.views.release import release_bp from critiquebrainz.frontend.views.work import work_bp from critiquebrainz.frontend.views.event import event_bp from critiquebrainz.frontend.views.mapping import mapping_bp from critiquebrainz.frontend.views.user import user_bp from critiquebrainz.frontend.views.profile import profile_bp from critiquebrainz.frontend.views.place import place_bp from critiquebrainz.frontend.views.profile_apps import profile_apps_bp from critiquebrainz.frontend.views.login import login_bp from critiquebrainz.frontend.views.oauth import oauth_bp from critiquebrainz.frontend.views.reports import reports_bp from critiquebrainz.frontend.views.moderators import moderators_bp from critiquebrainz.frontend.views.log import log_bp from critiquebrainz.frontend.views.comment import comment_bp from critiquebrainz.frontend.views.rate import rate_bp from critiquebrainz.frontend.views.statistics import statistics_bp app.register_blueprint(frontend_bp) app.register_blueprint(review_bp, url_prefix='/review') app.register_blueprint(search_bp, url_prefix='/search') app.register_blueprint(artist_bp, url_prefix='/artist') app.register_blueprint(label_bp, url_prefix='/label') app.register_blueprint(release_group_bp, url_prefix='/release-group') app.register_blueprint(release_bp, url_prefix='/release') app.register_blueprint(work_bp, url_prefix='/work') app.register_blueprint(event_bp, url_prefix='/event') app.register_blueprint(place_bp, url_prefix='/place') app.register_blueprint(mapping_bp, url_prefix='/mapping') app.register_blueprint(user_bp, url_prefix='/user') app.register_blueprint(profile_bp, url_prefix='/profile') app.register_blueprint(profile_apps_bp, url_prefix='/profile/applications') app.register_blueprint(login_bp, url_prefix='/login') app.register_blueprint(oauth_bp, url_prefix='/oauth') app.register_blueprint(reports_bp, url_prefix='/reports') app.register_blueprint(log_bp, url_prefix='/log') app.register_blueprint(moderators_bp, url_prefix='/moderators') app.register_blueprint(comment_bp, url_prefix='/comments') app.register_blueprint(rate_bp, url_prefix='/rate') app.register_blueprint(statistics_bp, url_prefix='/statistics') return app
def display_obituary(): return [ html.H2( gettext( "Evolution of the number of deaths published on obituary websites 2020 vs 2019" )), dcc.Markdown( get_translation( fr=""" Les données rapportées sont téléchargées des sites mortuaires belges (inmemoriam.be, necro.sudpress.be, dansnospensees.be). Au total, nous capturons environ 1/3 des décès en Belgique. Nous pensons que cela est suffisamment représentatif de la situation de surmortalité due au COVID19. La Flandre et Bruxelles semblent sous représentés dans les sites belges et reflète dès lors davantage la situation en Wallonie. """, en=""" The reported data are crawled from the Belgian (inmemoriam.be, necro.sudpress.be, dansnospensees.be) mortuary sites daily. In total, we capture around 1/3 of the daily deaths in Belgium with these data. We believe that this is sufficiently representative of the excess mortality situation due to COVID19. Flanders and Brussels seem underrepresented in Belgian sites and therefore more closely reflect the situation in Wallonia. """, )), dbc.Row([ dbc.Col(dcc.Graph(id='inmemoriam', figure=inmemoriam_plot(), config=dict(locale=str(get_locale()))), width=12, lg=6), dbc.Col(dcc.Graph(id='sudpress', figure=sudpresse_plot(), config=dict(locale=str(get_locale()))), width=12, lg=6), dbc.Col(dcc.Graph(id='dansnospensees', figure=dansnospensees_plot(), config=dict(locale=str(get_locale()))), width=12, lg=6), dbc.Col(dcc.Graph(id='allbeobituary', figure=allbeobituary_plot(), config=dict(locale=str(get_locale()))), width=12, lg=6), #dbc.Col(dcc.Graph(id='avisdeces', # figure=avideces_plot(), # config=dict(locale=str(get_locale()))), # width=12, lg=6), ]), html.H2( gettext( "Ratio of number of deaths published on obituary websites 2020/2019" )), dcc.Markdown( get_translation( fr=""" Ce graphique montre la surmortalité instantanée en Belgique par rapport à 2019. Un ratio de 2 signifie que nous avons 2x plus de morts qu'en 2019 et un ratio de 1 signie le même nombre de morts. Afin de réduire l'effet due au fluctuation journalière, ce ratio est calculé sur une fenêtre (glissante) de 7 jours. """, en=""" This graph shows the instant excess mortality in Belgium compared to 2019. A ratio of 2 means that we have 2x more deaths than in 2019 and a ratio of 1 means the same number of deaths. In order to reduce the effect due to the daily fluctuation, this ratio is calculated on a (sliding) window of 7 days. """, )), dbc.Row([ dbc.Col( dcc.Graph(id='rollinratio_obituary', figure=rolling_ratio_plot(), config=dict(locale=str(get_locale())))), ]), html.H2( gettext( "Ratio of number of deaths published on obituary websites 2020/ average 2019" )), dcc.Markdown( get_translation( fr=""" Même graphique que le précédent, mais le ratio est calculé par rapport à la moyenne 2019 pour éviter d'ajouter des fluctuations dues à 2019. """, en=""" Same graph as the previous one, but the ratio is calculated relative to the 2019 average to avoid adding fluctuations due to 2019. """, )), dbc.Row([ dbc.Col( dcc.Graph(id='ratio_obituary', figure=ratio_plot(), config=dict(locale=str(get_locale())))), ]), html.H2( gettext( "Total number of deaths published on obituary websites 2020/2019" )), dbc.Row([ dbc.Col(dcc.Graph(id='allbeobituarybar', figure=bar_plot_be(), config=dict(locale=str(get_locale()))), width=12, lg=6), #dbc.Col(dcc.Graph(id='allfrobituarybar', # figure=bar_plot_fr(), # config=dict(locale=str(get_locale()))), # width=12, lg=6) ]), display_source_providers(source_inmemoriam, source_necro_sudpress) ]
def before_request(): #this is called before every view function if current_user.is_authenticated: current_user.last_seen = datetime.utcnow( ) #updating last seen value at every request db.session.commit() g.locale = str(get_locale())
def home(): locale = get_locale() return render_template('app.html', first_week_day=locale.first_week_day + 1)
def municipalities(): return [ html.H2( gettext( get_translation(en="Number of cases per municipality", fr="Nombre de cas par commune"))), html.P( gettext( get_translation( fr= """C'est le nombre de cas testés positifs rapportés par Sciensano. Le nombre de cas positifs réel peut être (beaucoup) plus important. Notez que le nombre de tests quotidien varie également. Voir notre page testing. """, en=""" This is the number of positive test cases reported by Sciensano. The number of actual positive cases can be (much) higher. Note that the number of daily tests varies also. See our testing page. """))), html.H3( gettext( get_translation( en= "Incidence: Number of cases/100K inhabitants over the past 14 days", fr= "Incidence: Nombre de cas/100K habitants sur les 14 derniers jours" ))), html.H4( get_translation( en="""click on a municipality to see the cases barplot""", fr= """cliquez sur une commune pour observer l'historique des cas""", )), dbc.Row([ dbc.Col(display_graphic(id='map_cases_incidence_nis5', figure=map_cases_incidence_nis5(), config=dict(locale=str(get_locale()))), className="col-12"), ]), dbc.Row([ dbc.Col( display_graphic(id='cases-overview-histogram', style={"display": "none"}, figure=barplot_communes(), config=dict(locale=str(get_locale())))) ]), dbc.Row([ dbc.Col(display_graphic(id='cases-province-map', figure=bubble_map_cases_incidence_nis5(), config=dict(locale=str(get_locale()))), className="col-12"), ]), html.H3( get_translation( en="""Percentage of cases in the population since beginning""", fr="""Percentage de cas dans la population depuis le début""", )), dbc.Row([ dbc.Col( display_graphic(id='map_bubble_communes_since_beginning', figure=map_bubble_communes_since_beginning(), config=dict(locale=str(get_locale())))) ]), dbc.Row([ dbc.Col( display_graphic(id='map_communes_per_inhabitant', figure=map_communes_per_inhabitant(), config=dict(locale=str(get_locale())))), ]), display_source_providers(source_sciensano, source_map_communes, source_pop) ]
def before_request(): if current_user.is_authenticated: current_user.last_seen = datetime.utcnow() db.session.commit() g.search_form = SearchForm() g.locale = 'zh-tw' if str(get_locale()).startswith('zh') else str(get_locale())
def format_date_for_input(date): date_fmt = get_locale().date_formats['short'].pattern date_fmt = date_fmt \ .replace('MMMM', 'MM') \ .replace('MMM', 'MM') # force numerical months return format_date(date, date_fmt)
def before_request(): if current_user.is_authenticated: current_user.last_seen = datetime.utcnow() db.session.commit() g.locale = str(get_locale())
def isDbPagePublished(name): dbconf = getDbConf() return dbconf.get('page_' + name + '_published_' + get_locale().__str__(), dbconf.get('page_' + name + '_published')) is True
from app.main import bp from app import db from flask import render_template, flash, redirect, url_for, request, g, jsonify, current_app from app.main.forms import EditProfileForm, PostForm, MessageForm from flask_login import current_user, login_required from app.models import User, Post, Message, Notification from datetime import datetime from flask_babel import _, get_locale from guess_language import guess_language from app.translate import translate from app.main.forms import SearchForm from math import ceil ''' get_locale() 返回 zh_Hans_CN guess_language zh moment 只有在zh_CN才翻译 ''' @bp.before_request def before_request(): # 获取语言设置到g g.locale = str(get_locale()) if g.locale == 'zh_Hans_CN': # moment 认准zh_CN才翻译 g.locale = 'zh_CN' if current_user.is_authenticated: current_user.last_seen = datetime.utcnow() db.session.commit() g.search_form = SearchForm()
def before_request(): g.locale = str(get_locale())
def display_euromomo(): return [ html.H2(gettext("EUROMOMO data analysis")), html.H3(gettext("Overmortality Comparison")), dcc.Markdown( get_translation(fr="""\ EuroMOMO surveille et rapporte la mortalité dans 24 pays (ou morceaux de pays). Les mortalités ne sont pas données en chiffres brut, mais plutôt en z-scores, qui sont le nombre de déviations standard autour du nombre attendu de décès. Par exemple, étant donné un pays qui a environ 300 morts par jour (moyenne attendue), et que ce nombre varie habituellement avec une déviation standard de 30 (autrement dit, ~95% des décès se situent dans la tranche entre 240 et 360 décès). Imaginons qu'un jour, 345 décès soient constatés; le z-score serait alors de (345-300)/30=1.5. EuroMOMO donne les courbes des z-score chaque semaine. Le problème est qu'un z-score ne permet pas une comparaison aisée relative entre les pays. Il permet plutôt d'attirer l'attention sur une anomalie par rapport à la normale, mais il ne permet en aucun cas d'estimer l'excès de mortalité d'un pays à l'autre sur une même semaine. La formule d'un z-score est (x(t)-baseline) / sd. Il est tout à fait raisonnable de considérer que la baseline et l'écart type (sd) sont constant depuis la pandémie du COVID19. Si nous connaissons la mortalité hebdomadaire d'un pays pour deux semaines différentes, nous pouvons donc résoudre un système de deux équations à deux inconnues pour retrouver les valeurs baseline et sd propres à chaque pays. Voici les valeurs que nous avons retrouvées pour certains pays. | Country | baseline | sd | |--------------|----------|--------------------| | UK (England) | 10954 | 154 | | Netherlands | 3024 | 84 | | Belgium | 2166 | 68 | | France | 10391 | 251 | Nous avons tracés ci dessous la courbe x(t) ainsi retrouvée divisée par la baseline. Cette courbe nous donne une bonne estimation de la surmortalité chaque semaine dans les pays. """, en="""\ EuroMOMO monitors the mortality of 24 countries (or parts or them) and reports them on its website. The mortalities are not given in raw numbers, but rather as z-scores, which are the number of standard deviations around the expected number of death. For example, if a country has usually 300 deaths per day (expected baseline), but that number usually varies such that its standard deviation is 30 (i.e. 95% of the seen death are between 240 and 360), and that the number of death seen on a particular day is 345, then the z-score is (345-300)/(30)=1.5. EuroMOMO gives the z-score curves every week. The problem is that a z-score does not allow an easy relative comparison between countries. Rather, it draws attention to an abnormality compared to normal, but it does not in any case allow to estimate the excess mortality from one country to another over the same week. The formula for a z-score is (x(t)-baseline) / sd. It is entirely reasonable to consider that the baseline and the standard deviation (sd) have been constant since the COVID19 pandemic. If we know the weekly mortality of a country for two different weeks, we can therefore solve a system of two equations with two unknowns to find the baseline and sd values specific to each country. Here are the values that we found for certain countries. | Country | baseline | sd | |--------------|----------|--------------------| | UK (England) | 10954 | 154 | | Netherlands | 3024 | 84 | | Belgium | 2166 | 68 | | France | 10391 | 251 | We have plotted below the curve x (t) thus found divided by the baseline. This curve gives us a good estimate of the excess mortality each week in the countries. """)), dbc.Row([ dbc.Col( display_graphic(id='euromomo-ratio', figure=euromomo_ratio(), config=dict(locale=str(get_locale())))), ]), html.H3(gettext("Where are the peaks?")), custom_warning_box( gettext( "Z-scores CANNOT be compared country-to-country. The plot below can only be used to" " find when the peaks happened.")), dbc.Row([ dbc.Col( display_graphic(id='euromomo-zscores', figure=euromomo_zscores(), config=dict(locale=str(get_locale())))), ]), display_source_providers(source_euromomo) ]
def display_cases_correction(): return [ dcc.Markdown( get_translation(fr=""" ## Et si la première vague n'était pas correcte? """, )), *model_warning( dcc.Markdown( get_translation(fr=""" Nous entendons souvent que la deuxième vague est fort différente de la première, car celle-ci touche beaucoup plus les jeunes (c’est-à-dire la population active <60 ans, en bleu ci-dessus) que lors de la première vague qui touchait essentiellement les >60 ans (en rouge). C’est en effet ce que montrent les données brutes. """, )), dbc.Row([ dbc.Col( display_graphic(id='age-group-cases-real', figure=age_groups_pop_active_cases(), config=dict(locale=str(get_locale())))), ]), dcc.Markdown( get_translation(fr=""" Cependant, une phrase de la conférence de presse de Sciensano aujourd’hui peut nous laisser penser que ceci n’est pas correct et que nous pourrions légitimement redessiner la première vague afin que celle-ci colle plus avec la réalité. C’est l’exercice que nous faisons ici. Faisons d’abord quelques hypothèses qui nous paraissent réalistes. Supposons tout d'abord qu’une personne positive dans sa tranche d'âge aujourd’hui à la même probabilité de terminer hospitalisée qu’au début de l’épidémie. Appelons cette hypothèse la stabilité de la dangerosité du virus (cette hypothèse pourrait ne pas être vraie si sa virulence s´est affaiblie mais ceci n'a pas été démontré à l´heure actuelle). Sciensano annonce aujourd’hui durant la conférence de presse que, depuis le 22 juin, l'âge médian des personnes hospitalisées est de 65 ans, or avant cette date il était plutôt de 70 ans. Nous pouvons donc supposer que la distribution d’âge des personnes hospitalisées est restée relativement stable (merci à Sciensano de mettre les données à disposition pour que nous puissions confirmer ou infirmer cette hypothèse). En utilisant notre hypothèse de stabilité de la dangerosité du virus, cela signifierait qu’il doit y avoir environ la même proportion de cas positifs dans les tranches d'âge aujourd’hui que durant la première vague. Utilisons cette déduction pour tenter de corriger la courbe des contaminations de la première vague. Depuis le 22 juin, 14% des tests positifs concernent des personnes de plus de 60 ans. Le testing est beaucoup plus exhaustif aujourd’hui, nous allons donc supposer que cette proportion est correcte. Supposons que le nombre de personnes de plus de 60 ans contaminées était correct également durant la première vague. Cette hypothèse est probablement fausse puisque nous testions alors uniquement les cas symptomatiques, mais elle est cependant conservatrice pour notre exercice de correction de la courbe. Cela signifierait que nous pouvons multiplier le nombre de cas de moins de 60 ans par un facteur correctif 1/14% = 7.14. Nous obtenons alors cette courbe corrigée des cas positifs mettant en perspective l’importance de la première vague par rapport au rebond que nous connaissons depuis mi-juillet: """, )), dbc.Row([ dbc.Col( display_graphic( id='age-group-cases-corrected', figure=age_groups_pop_active_hypothetical(), config=dict(locale=str(get_locale())))), ]), display_source_providers(source_sciensano, )) ]
def get_currency_symbol(currency="GBP"): return numbers.get_currency_symbol(currency, locale=flask_babel.get_locale())
def index(): return '<h2>Locale: {}</h2>'.format(get_locale())
def display_brussels(): return [ html.H3(gettext("Tunnel traffic")), html.P( gettext( get_translation( fr= """Nombre de véhicules passant chaque heure dans les tunnels principaux de Bruxelles.""", en= """Number of vehicles passing every hour through the main tunnels of Brussels.""" ))), html.H3(gettext("Brussels tunnels traffic working days 7:00-8:00")), dbc.Row([ dbc.Col( dcc.Graph(id='brussels-tunnel', figure=brussels_tunnels(), config=dict(locale=str(get_locale())))), ]), html.H3( gettext( "Brussels tunnels relative traffic working days 7:00-8:00")), html.P( gettext( get_translation( fr= """Divisé par le nombre moyen de véhicules enregistré sur la période 1er Féb - 10 Mars""", en= """Divided by the average number of vehicles recorded over the period Feb 1 - March 10""" ))), dbc.Row([ dbc.Col( dcc.Graph(id='brussels-tunnel-ratio', figure=brussels_tunnels_ratio(), config=dict(locale=str(get_locale())))), ]), html.H3( gettext( "Brussels all tunnels relative traffic working days 7:00-8:00") ), html.P( gettext( get_translation( fr= """Divisé par le nombre moyen de véhicules enregistré sur la période 1er Féb - 10 Mars""", en= """Divided by the average number of vehicles recorded over the period Feb 1 - March 10""" ))), dbc.Row([ dbc.Col( dcc.Graph(id='brussels-tunnel-ratio', figure=brussels_alltunnels_ratio(), config=dict(locale=str(get_locale())))), ]), display_source_providers(source_brussels_mobility), html.H2(gettext("Apple Mobility Report")), dbc.Row([ dbc.Col( dcc.Graph(id='eucities-apple', figure=apple_mobility_plot_cities(), config=dict(locale=str(get_locale())))), ]), display_source_providers(source_apple_mobility), ]
def display_facebook_eu(): return [ html.H3( get_translation(fr="Graphs based on the number of FB users who moved between two EU countries in a 24 hour period (avg 7 days)", en="Graphs based on the number of FB users who moved between two EU countries in a 24 hour period (avg 7 days)")), html.Label([gettext(get_translation(fr="Destination Country", en="Destination Country")), dcc.Dropdown( id='countries-dropdown-eu', options=[{'label': c, 'value': c} for c in countries], value='belgium', clearable=False )], style=dict(width='50%')), html.Label([gettext(get_translation(fr="Jour", en="Day")), dcc.Dropdown( id='countries-day-dropdown-eu', options=[{'label': 'all-days-moving-avg-7', 'value': 9}, {'label': 'all-days', 'value': 8}, {'label': 'monday', 'value': 0}, {'label': 'tuesday', 'value': 1}, {'label': 'wednesday', 'value': 2}, {'label': 'thursday', 'value': 3}, {'label': 'friday', 'value': 4}, {'label': 'saturday', 'value': 5}, {'label': 'sunday', 'value': 6}], value=8, clearable=False )], style=dict(width='50%')), dcc.Graph(id='graph-countries-eu'), dbc.Row([ dbc.Col(display_graphic(id='plot_tot_travel', figure=plot_tot_travel(), config=dict(locale=str(get_locale())))), ]), dbc.Row([ dbc.Col(display_graphic(id='plot_tot_travel', figure=plot_tot_cases(), config=dict(locale=str(get_locale())))), ]), dbc.Row([ dbc.Col(display_graphic(id='plot_tot_fraction_countries', figure=plot_tot_fraction_countries(), config=dict(locale=str(get_locale())))), ]), dbc.Row([ dbc.Col(display_graphic(id='plot_in_per_million', figure=plot_in_per_million(), config=dict(locale=str(get_locale())))), ]), dbc.Row([ dbc.Col(display_graphic(id='plot_imported_cases_per_millions', figure=plot_imported_cases_per_millions(), config=dict(locale=str(get_locale())))), ]), dbc.Row([ dbc.Col(display_graphic(id='fraction_imported_cases_over_tot_cases', figure=fraction_imported_cases_over_tot_cases(), config=dict(locale=str(get_locale())))), ]), display_source_providers(source_facebook) ]
def before_request(): app.logger.debug('before_request()') g.locale = str(get_locale())
def _get_locale(): locale = flask_babel.get_locale() if locale is None: locale = get_default_locale() return locale
def create_app(debug=None, config_path=None): app = CustomFlask( import_name=__name__, use_flask_uuid=True, use_debug_toolbar=True, ) # Configuration files app.config.from_pyfile(os.path.join( os.path.dirname(os.path.realpath(__file__)), '..', '..', 'default_config.py' )) app.config.from_pyfile(os.path.join( os.path.dirname(os.path.realpath(__file__)), '..', '..', 'consul_config.py' ), silent=True) app.config.from_pyfile(os.path.join( os.path.dirname(os.path.realpath(__file__)), '..', '..', 'custom_config.py' ), silent=True) if config_path: app.config.from_pyfile(config_path) if debug is not None: app.debug = debug # Error handling from critiquebrainz.frontend.error_handlers import init_error_handlers init_error_handlers(app) # Static files from critiquebrainz.frontend import static_manager static_manager.read_manifest() app.init_loggers( file_config=app.config.get("LOG_FILE"), email_config=app.config.get("LOG_EMAIL"), sentry_config=app.config.get("LOG_SENTRY"), ) # Database from critiquebrainz.db import init_db_engine init_db_engine(app.config.get("SQLALCHEMY_DATABASE_URI")) add_robots(app) # MusicBrainz Database from critiquebrainz.frontend.external import musicbrainz_db musicbrainz_db.init_db_engine(app.config.get('MB_DATABASE_URI')) # Redis (cache) from brainzutils import cache if "REDIS_HOST" in app.config and \ "REDIS_PORT" in app.config and \ "REDIS_NAMESPACE" in app.config: cache.init( host=app.config["REDIS_HOST"], port=app.config["REDIS_PORT"], namespace=app.config["REDIS_NAMESPACE"], ) else: logging.warning("Redis is not defined in config file. Skipping initialization.") from critiquebrainz.frontend import babel babel.init_app(app) from critiquebrainz.frontend import login login.login_manager.init_app(app) from critiquebrainz.frontend.login.provider import MusicBrainzAuthentication login.mb_auth = MusicBrainzAuthentication( name='musicbrainz', client_id=app.config['MUSICBRAINZ_CLIENT_ID'], client_secret=app.config['MUSICBRAINZ_CLIENT_SECRET'], authorize_url="https://musicbrainz.org/oauth2/authorize", access_token_url="https://musicbrainz.org/oauth2/token", base_url="https://musicbrainz.org/", ) # APIs from critiquebrainz.frontend.external import mbspotify mbspotify.init(app.config['MBSPOTIFY_BASE_URI'], app.config['MBSPOTIFY_ACCESS_KEY']) from critiquebrainz.frontend.external import musicbrainz musicbrainz.init( app_name=app.config['MUSICBRAINZ_USERAGENT'] or "CritiqueBrainz Custom", app_version="1.0", hostname=app.config['MUSICBRAINZ_HOSTNAME'] or "musicbrainz.org", ) # Template utilities app.jinja_env.add_extension('jinja2.ext.do') from critiquebrainz.utils import reformat_date, reformat_datetime, track_length, parameterize from critiquebrainz.frontend.external.musicbrainz_db.entities import get_entity_by_id app.jinja_env.filters['date'] = reformat_date app.jinja_env.filters['datetime'] = reformat_datetime app.jinja_env.filters['track_length'] = track_length app.jinja_env.filters['parameterize'] = parameterize app.jinja_env.filters['entity_details'] = get_entity_by_id from flask_babel import Locale, get_locale app.jinja_env.filters['language_name'] = lambda language_code: Locale(language_code).get_language_name(get_locale()) app.context_processor(lambda: dict(get_static_path=static_manager.get_static_path)) # Blueprints from critiquebrainz.frontend.views.index import frontend_bp from critiquebrainz.frontend.views.review import review_bp from critiquebrainz.frontend.views.search import search_bp from critiquebrainz.frontend.views.artist import artist_bp from critiquebrainz.frontend.views.release_group import release_group_bp from critiquebrainz.frontend.views.release import release_bp from critiquebrainz.frontend.views.event import event_bp from critiquebrainz.frontend.views.mapping import mapping_bp from critiquebrainz.frontend.views.user import user_bp from critiquebrainz.frontend.views.profile import profile_bp from critiquebrainz.frontend.views.place import place_bp from critiquebrainz.frontend.views.profile_apps import profile_apps_bp from critiquebrainz.frontend.views.login import login_bp from critiquebrainz.frontend.views.oauth import oauth_bp from critiquebrainz.frontend.views.reports import reports_bp from critiquebrainz.frontend.views.moderators import moderators_bp from critiquebrainz.frontend.views.log import log_bp app.register_blueprint(frontend_bp) app.register_blueprint(review_bp, url_prefix='/review') app.register_blueprint(search_bp, url_prefix='/search') app.register_blueprint(artist_bp, url_prefix='/artist') app.register_blueprint(release_group_bp, url_prefix='/release-group') app.register_blueprint(release_bp, url_prefix='/release') app.register_blueprint(event_bp, url_prefix='/event') app.register_blueprint(place_bp, url_prefix='/place') app.register_blueprint(mapping_bp, url_prefix='/mapping') app.register_blueprint(user_bp, url_prefix='/user') app.register_blueprint(profile_bp, url_prefix='/profile') app.register_blueprint(profile_apps_bp, url_prefix='/profile/applications') app.register_blueprint(login_bp, url_prefix='/login') app.register_blueprint(oauth_bp, url_prefix='/oauth') app.register_blueprint(reports_bp, url_prefix='/reports') app.register_blueprint(log_bp, url_prefix='/log') app.register_blueprint(moderators_bp, url_prefix='/moderators') return app
def create(): for entity_type in ENTITY_TYPES: entity_id = request.args.get(entity_type) if entity_id: break if not entity_id: flash.info(gettext("Please choose an entity to review.")) return redirect(url_for('search.selector', next=url_for('.create'))) if current_user.is_blocked: flash.error( gettext("You are not allowed to write new reviews because your " "account has been blocked by a moderator.")) return redirect(url_for('user.reviews', user_id=current_user.id)) # Checking if the user already wrote a review for this entity review = Review.query.filter_by(user=current_user, entity_id=entity_id).first() if review: flash.error( gettext("You have already published a review for this entity!")) return redirect(url_for('review.entity', id=review.id)) form = ReviewCreateForm(default_language=get_locale()) if form.validate_on_submit(): if current_user.is_review_limit_exceeded: flash.error( gettext("You have exceeded your limit of reviews per day.")) return redirect(url_for('user.reviews', user_id=current_user.id)) is_draft = form.state.data == 'draft' review = Review.create(user=current_user, entity_id=entity_id, entity_type=entity_type, text=form.text.data, license_id=form.license_choice.data, language=form.language.data, is_draft=is_draft) if is_draft: flash.success(gettext("Review has been saved!")) else: flash.success(gettext("Review has been published!")) return redirect(url_for('.entity', id=review.id)) entity = musicbrainz.get_entity_by_id(entity_id, entity_type) if not entity: flash.error( gettext( "You can only write a review for an entity that exists on MusicBrainz!" )) return redirect(url_for('search.selector', next=url_for('.create'))) if entity_type == 'release_group': spotify_mappings = mbspotify.mappings(entity_id) soundcloud_url = soundcloud.get_url(entity_id) return render_template('review/modify/write.html', form=form, entity_type=entity_type, entity=entity, spotify_mappings=spotify_mappings, soundcloud_url=soundcloud_url) return render_template('review/modify/write.html', form=form, entity_type=entity_type, entity=entity)
def display_age_groups(): return [ html.H2(gettext("Overall (Weekly) Mortality Only (STATBEL Data)")), dbc.Row([ dbc.Col( dcc.Graph(id='age-group-death-statbel', figure=death_age_groups("stack"), config=dict(locale=str(get_locale())))), ]), dbc.Row([ dbc.Col( dcc.Graph(id='age-group-death-statbel-stack', figure=death_age_groups(), config=dict(locale=str(get_locale())))), ]), html.H2(gettext("History of death 85+ only")), dbc.Row([ dbc.Col( dcc.Graph(id='age-group-death-statbel-hist', figure=death_85plus_hist(), config=dict(locale=str(get_locale())))), ]), dbc.Row([ dbc.Col( dcc.Graph(id='death-statbel-85+-hist-cum', figure=death_85plus_hist_cum(), config=dict(locale=str(get_locale())))), ]), html.H2(gettext("History of death all population")), dbc.Row([ dbc.Col( dcc.Graph(id='age-group-death-statbel-hist', figure=death_hist(), config=dict(locale=str(get_locale())))), ]), dbc.Row([ dbc.Col( dcc.Graph(id='death-statbell-all-hist-cum', figure=death_plus_hist_cum(), config=dict(locale=str(get_locale())))), ]), display_source_providers(source_statbel), html.H2(gettext("COVID (Daily) Mortality (Sciensano Data)")), dbc.Row([ dbc.Col( dcc.Graph(id='age-group-death', figure=age_groups_death(), config=dict(locale=str(get_locale())))), ]), dbc.Row([ dbc.Col( dcc.Graph(id='age-group-death-stack', figure=age_groups_death("stack"), config=dict(locale=str(get_locale())))), ]), dbc.Row([ dbc.Col( dcc.Graph(id='age-group-death-pie', figure=age_groups_death_pie(), config=dict(locale=str(get_locale())))), ]), display_source_providers(source_sciensano) ]