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

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

## 49 statements 38 run 11 missing 0 excluded 3 partial

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'''

2 import io

3 import os

4 import json

5 import gramex.cache

6 from hashlib import md5

7 from tornado.gen import coroutine, Return

8 from gramex.config import variables, app_log, merge

9

10

11 def join(*args):

12 return os.path.normpath(os.path.join(*args))

13

14

15 folder = os.path.dirname(os.path.abspath(__file__))

16 config_file = join(folder, 'config.yaml')

17 uicomponents_path = join(folder, 'bootstrap-theme.scss')

18 cache_dir = join(variables['GRAMEXDATA'], 'apps', 'ui')

19 bootstrap_path = join(folder, 'node_modules', 'bootstrap', 'scss', 'bootstrap')

20 sass_path = join(folder, 'node_modules', 'node-sass', 'bin', 'node-sass')

21 if 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)

23

24

25@coroutine

26 def 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}

33

34 # Set default args

35 config = gramex.cache.open(config_file)

36 merge(args, config.get('defaults'), mode='setdefault')

37

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]

42

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'])

51

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')

74

75 handler.set_header('Content-Type', 'text/css')

76 raise Return(gramex.cache.open(cache_path, 'bin', mode='rb'))