Coverage for gramex\apps\ui\__init__.py : 75%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1'''Main UI application'''
2import io
3import os
4import json
5import gramex.cache
6from hashlib import md5
7from tornado.gen import coroutine, Return
8from gramex.config import variables, app_log, merge
11def join(*args):
12 return os.path.normpath(os.path.join(*args))
15folder = os.path.dirname(os.path.abspath(__file__))
16config_file = join(folder, 'config.yaml')
17uicomponents_path = join(folder, 'bootstrap-theme.scss')
18cache_dir = join(variables['GRAMEXDATA'], 'apps', 'ui')
19bootstrap_path = join(folder, 'node_modules', 'bootstrap', 'scss', 'bootstrap')
20sass_path = join(folder, 'node_modules', 'node-sass', 'bin', 'node-sass')
21if not os.path.exists(cache_dir): 21 ↛ 22line 21 didn't jump to line 22, because the condition on line 21 was never true
22 os.makedirs(cache_dir)
25@coroutine
26def sass(handler, template=uicomponents_path):
27 '''
28 Return a bootstrap theme based on the custom SASS variables provided.
29 '''
30 args = dict(variables.get('ui-bootstrap', {}))
31 args.update({key: handler.get_arg(key) for key in handler.args})
32 args = {key: val for key, val in args.items() if val}
34 # Set default args
35 config = gramex.cache.open(config_file)
36 merge(args, config.get('defaults'), mode='setdefault')
38 cache_key = {'template': template, 'args': args}
39 cache_key = json.dumps(
40 cache_key, sort_keys=True, ensure_ascii=True).encode('utf-8')
41 cache_key = md5(cache_key).hexdigest()[:5]
43 # Replace fonts from config file, if available
44 google_fonts = set()
45 for key in ('font-family-base', 'headings-font-family'):
46 if key in args and args[key] in config['fonts']:
47 fontinfo = config['fonts'][args[key]]
48 args[key] = fontinfo['stack']
49 if 'google' in fontinfo: 49 ↛ 45line 49 didn't jump to line 45, because the condition on line 49 was never false
50 google_fonts.add(fontinfo['google'])
52 # Cache based on the dict and config as template.<cache-key>.css
53 base = os.path.splitext(os.path.basename(template))[0] + '.' + cache_key
54 cache_path = join(cache_dir, base + '.css')
55 if not os.path.exists(cache_path) or os.stat(template).st_mtime > os.stat(cache_path).st_mtime: 55 ↛ 57line 55 didn't jump to line 57, because the condition on line 55 was never true
56 # Create a SCSS file based on the args
57 scss_path = join(cache_dir, base + '.scss')
58 with io.open(scss_path, 'wb') as handle:
59 result = gramex.cache.open(template, 'template').generate(
60 variables=args,
61 uicomponents_path=uicomponents_path.replace('\\', '/'),
62 bootstrap_path=bootstrap_path.replace('\\', '/'),
63 google_fonts=google_fonts,
64 )
65 handle.write(result)
66 # Run sass to generate the output
67 options = ['--output-style', 'compressed']
68 proc = gramex.cache.Subprocess(
69 ['node', sass_path, scss_path, cache_path] + options)
70 out, err = yield proc.wait_for_exit()
71 if proc.proc.returncode:
72 app_log.error('node-sass error: %s', err)
73 raise RuntimeError('Compilation failure')
75 handler.set_header('Content-Type', 'text/css')
76 raise Return(gramex.cache.open(cache_path, 'bin', mode='rb'))