__init__.py 2.83 KB
Newer Older
Pierre Dittgen's avatar
Pierre Dittgen committed
1
import json
Christophe Benz's avatar
Christophe Benz committed
2
import logging
3
import os
4
import re
5
from pathlib import Path
6
from urllib.parse import quote_plus
7

8
import cachecontrol
9
10
import flask
import jinja2
Christophe Benz's avatar
Christophe Benz committed
11
12
import opendataschema
import pkg_resources
13
14
15
import requests
import tableschema

16
from . import config
17

Christophe Benz's avatar
Christophe Benz committed
18
19
log = logging.getLogger(__name__)

Christophe Benz's avatar
Christophe Benz committed
20
21
22
distribution = pkg_resources.get_distribution("validata-ui")
VERSION = distribution.version

23

24
25
26
def generate_schema_from_url_func(session):
    """Generates a function that encloses session"""

27
28
29
30
31
    def tableschema_from_url(url):
        response = session.get(url)
        response.raise_for_status()
        descriptor = response.json()
        return tableschema.Schema(descriptor)
32

33
34
35
    return tableschema_from_url


36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
def is_http_url(ref) -> bool:
    return isinstance(ref, str) and re.match("https?://", ref)


class SchemaCatalogRegistry:
    """Retain section_name -> catalog url matching
    and creates SchemaCatalog instance on demand"""

    def __init__(self, session):
        self.session = session
        self.url_map = {}

    def add_ref(self, name, url):
        self.url_map[name] = url

    def build_schema_catalog(self, name):
        if name in self.url_map:
            catalog_url = self.url_map[name]
            return opendataschema.SchemaCatalog(catalog_url, session=self.session)
        return None


58
59
caching_session = cachecontrol.CacheControl(requests.Session())
tableschema_from_url = generate_schema_from_url_func(caching_session)
60

61
# And load schema catalogs which URLs are found in homepage_config.json
62
schema_catalog_registry = SchemaCatalogRegistry(caching_session)
63
if config.HOMEPAGE_CONFIG:
Christophe Benz's avatar
Christophe Benz committed
64
    log.info("Initializing homepage sections...")
65
    for section in config.HOMEPAGE_CONFIG['sections']:
Christophe Benz's avatar
Christophe Benz committed
66
67
        name = section['name']
        log.info('Initializing homepage section "{}"...'.format(name))
68
69
70
        catalog_ref = section.get('catalog')
        if is_http_url(catalog_ref):
            schema_catalog_registry.add_ref(name, catalog_ref)
71
    log.info("...done")
72
73

# Flask things
74
app = flask.Flask(__name__)
75
76
app.secret_key = config.SECRET_KEY

Christophe Benz's avatar
Christophe Benz committed
77
78
79
80
81
matomo = None
if config.MATOMO_AUTH_TOKEN and config.MATOMO_BASE_URL and config.MATOMO_SITE_ID:
    from flask_matomo import Matomo
    matomo = Matomo(app, matomo_url=config.MATOMO_BASE_URL,
                    id_site=config.MATOMO_SITE_ID, token_auth=config.MATOMO_AUTH_TOKEN)
82

83
84
85
86
# Jinja2 url_quote_plus custom filter
# https://stackoverflow.com/questions/12288454/how-to-import-custom-jinja2-filters-from-another-file-and-using-flask
blueprint = flask.Blueprint('filters', __name__)

87

88
89
90
91
92
93
@jinja2.contextfilter
@blueprint.app_template_filter()
def urlencode(context, value):
    return quote_plus(value)


94
95
@app.context_processor
def inject_version():
Christophe Benz's avatar
Christophe Benz committed
96
    global VERSION
97
98
99
    return {"validata_ui_version": VERSION}


100
# Keep this import after app initialisation (to avoid cyclic imports)
101
from . import views  # noqa isort:skip