<commit_before>import os
from flask import (
    Blueprint, abort, redirect, url_for, send_from_directory, request, current_app)
from flask_login import current_user
from sqlalchemy.sql.expression import true
from goodtablesio import models
from goodtablesio import settings
from goodtablesio.services import database
from goodtablesio.models.job import Job
from goodtablesio.models.source import Source
from goodtablesio.utils.frontend import render_component
from goodtablesio.utils.backend import no_cache


# Module API

site = Blueprint('site', __name__)


# goodtables.io

@site.route('/')
def home():
    if current_user.is_authenticated:
        return redirect(url_for('site.dashboard'))
    return render_component('Landing')


@site.route('/about')
def about():
    return render_component('About')


@site.route('/dashboard')
def dashboard():
    if not current_user.is_authenticated:
        return redirect(url_for('site.home'))

    # Get user sources
    sources = (database['session'].query(Source).join(Job, isouter=True).
               filter(Source.users.any(id=current_user.id)).
               filter(Source.active == true()).
               order_by(Job.created.desc().nullslast(), Source.name).all())

    if sources:
        sources = [source.to_api(with_last_job=True) for source in sources]

    return render_component('Dashboard', props={
        'sources': sources,
    })


@site.route('/jobs')
def jobs():
    # TODO: remove duplication between `dashboard/jobs`

    if not current_user.is_authenticated:
        return redirect(url_for('site.home'))

    # Get user sources
    sources = (database['session'].query(Source).join(Job, isouter=True).
               filter(Source.users.any(id=current_user.id)).
               filter(Source.active == true()).
               order_by(Job.created.desc().nullslast(), Source.name).all())

    if sources:
        sources = [source.to_api(with_last_job=True) for source in sources]

    return render_component('Jobs', props={
        'sources': sources,
    })


@site.route('/github/<owner>/<repo>')
def source_github(owner, repo):
    return _source('github', '/'.join([owner, repo]))


@site.route('/github/<owner>/<repo>/jobs/<int:job>')
def source_github_job(owner, repo, job):
    return _source('github', '/'.join([owner, repo]), job)


@site.route('/s3/<bucket>')
def source_s3(bucket):
    return _source('s3', bucket)


@site.route('/s3/<bucket>/jobs/<int:job>')
def source_s3_job(bucket, job):
    return _source('s3', bucket, job)


@site.route('/settings')
def settings_page():
    if not current_user.is_authenticated:
        return redirect(url_for('site.home'))
    return render_component('Settings')


@site.route('/badge/<integration_name>/<path:source_name>.svg')
@no_cache
def badge(integration_name, source_name):

    last_status = (
        database['session'].query(models.job.Job.status).
        join(models.source.Source).
        filter(models.job.Job.integration_name == integration_name).
        filter(models.job.Job.status.in_(['success', 'failure', 'error'])).
        filter((models.source.Source.name == source_name) |
               (models.source.Source.id == source_name)).
        order_by(models.job.Job.finished.desc()).
        limit(1).
        one_or_none()
    )

    style = request.args.get('style', 'flat')
    if style not in ('flat', 'flat-square'):
        style = 'flat'

    if last_status:
        last_status = last_status[0]
    else:
        last_status = 'unknown'

    file_name = 'data-{status}-{style}.svg'.format(
        status=last_status, style=style)

    file_path = os.path.join(
        os.path.dirname(__file__), 'badges')

    return send_from_directory(file_path, file_name, mimetype='image/svg+xml')


# try.goodtables.io

# To have an ability to dev it:
# - add to /etc/hosts: 127.0.0.1 goodtables.dev try.goodtables.dev
# - set in .env BASE_URL=http://goodtables.dev:5000
@site.route('/', subdomain=settings.GTIO_TRY_SUBDOMAIN)
def try_goodtables():
    return render_component('DemoForm', props={
        'apiUrl': settings.DEMO_API_URL,
        'apiToken': settings.DEMO_API_TOKEN,
        'apiSourceId': settings.DEMO_API_SOURCE_ID,
    })


@site.route('/public/<path:filename>', subdomain='try')
def try_goodtables_public(filename):
    return send_from_directory(current_app.static_folder, filename)


# Internal

def _source(integration_name, name, job_number=None):

    # Get source
    source = (database['session'].query(Source).
              filter(Source.integration_name == integration_name).
              filter(Source.name == name).
              first())
    if not source:
        abort(404)

    # Check access
    if not _check_source_access(source):
        abort(401, 'You are not authorized to access this source')

    # Get selected job
    if job_number:
        job = (database['session'].query(Job).
               filter(Job.source == source).<commit_msg>Configure subdomain in assets requests as well<commit_after>import os
from flask import (
    Blueprint, abort, redirect, url_for, send_from_directory, request, current_app)
from flask_login import current_user
from sqlalchemy.sql.expression import true
from goodtablesio import models
from goodtablesio import settings
from goodtablesio.services import database
from goodtablesio.models.job import Job
from goodtablesio.models.source import Source
from goodtablesio.utils.frontend import render_component
from goodtablesio.utils.backend import no_cache


# Module API

site = Blueprint('site', __name__)


# goodtables.io

@site.route('/')
def home():
    if current_user.is_authenticated:
        return redirect(url_for('site.dashboard'))
    return render_component('Landing')


@site.route('/about')
def about():
    return render_component('About')


@site.route('/dashboard')
def dashboard():
    if not current_user.is_authenticated:
        return redirect(url_for('site.home'))

    # Get user sources
    sources = (database['session'].query(Source).join(Job, isouter=True).
               filter(Source.users.any(id=current_user.id)).
               filter(Source.active == true()).
               order_by(Job.created.desc().nullslast(), Source.name).all())

    if sources:
        sources = [source.to_api(with_last_job=True) for source in sources]

    return render_component('Dashboard', props={
        'sources': sources,
    })


@site.route('/jobs')
def jobs():
    # TODO: remove duplication between `dashboard/jobs`

    if not current_user.is_authenticated:
        return redirect(url_for('site.home'))

    # Get user sources
    sources = (database['session'].query(Source).join(Job, isouter=True).
               filter(Source.users.any(id=current_user.id)).
               filter(Source.active == true()).
               order_by(Job.created.desc().nullslast(), Source.name).all())

    if sources:
        sources = [source.to_api(with_last_job=True) for source in sources]

    return render_component('Jobs', props={
        'sources': sources,
    })


@site.route('/github/<owner>/<repo>')
def source_github(owner, repo):
    return _source('github', '/'.join([owner, repo]))


@site.route('/github/<owner>/<repo>/jobs/<int:job>')
def source_github_job(owner, repo, job):
    return _source('github', '/'.join([owner, repo]), job)


@site.route('/s3/<bucket>')
def source_s3(bucket):
    return _source('s3', bucket)


@site.route('/s3/<bucket>/jobs/<int:job>')
def source_s3_job(bucket, job):
    return _source('s3', bucket, job)


@site.route('/settings')
def settings_page():
    if not current_user.is_authenticated:
        return redirect(url_for('site.home'))
    return render_component('Settings')


@site.route('/badge/<integration_name>/<path:source_name>.svg')
@no_cache
def badge(integration_name, source_name):

    last_status = (
        database['session'].query(models.job.Job.status).
        join(models.source.Source).
        filter(models.job.Job.integration_name == integration_name).
        filter(models.job.Job.status.in_(['success', 'failure', 'error'])).
        filter((models.source.Source.name == source_name) |
               (models.source.Source.id == source_name)).
        order_by(models.job.Job.finished.desc()).
        limit(1).
        one_or_none()
    )

    style = request.args.get('style', 'flat')
    if style not in ('flat', 'flat-square'):
        style = 'flat'

    if last_status:
        last_status = last_status[0]
    else:
        last_status = 'unknown'

    file_name = 'data-{status}-{style}.svg'.format(
        status=last_status, style=style)

    file_path = os.path.join(
        os.path.dirname(__file__), 'badges')

    return send_from_directory(file_path, file_name, mimetype='image/svg+xml')


# try.goodtables.io

# To have an ability to dev it:
# - add to /etc/hosts: 127.0.0.1 goodtables.dev try.goodtables.dev
# - set in .env BASE_URL=http://goodtables.dev:5000
@site.route('/', subdomain=settings.GTIO_TRY_SUBDOMAIN)
def try_goodtables():
    return render_component('DemoForm', props={
        'apiUrl': settings.DEMO_API_URL,
        'apiToken': settings.DEMO_API_TOKEN,
        'apiSourceId': settings.DEMO_API_SOURCE_ID,
    })


@site.route('/public/<path:filename>', subdomain=settings.GTIO_TRY_SUBDOMAIN)
def try_goodtables_public(filename):
    return send_from_directory(current_app.static_folder, filename)


# Internal

def _source(integration_name, name, job_number=None):

    # Get source
    source = (database['session'].query(Source).
              filter(Source.integration_name == integration_name).
              filter(Source.name == name).
              first())
    if not source:
        abort(404)

    # Check access
    if not _check_source_access(source):
        abort(401, 'You are not authorized to access this source')

    # Get selected job
    if job_number:
        job = (database['session'].query(Job).
               filter(Job.source == source).
{'fraction_non_alphanumeric': 0.139321999798813, 'fraction_numerical': 0.004828488079670053, 'mean_word_length': 3.4582959641255604, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6864238', 'n_tokens_mistral': 3129, 'n_tokens_neox': 3018, 'n_words': 621}