diff --git a/compose/django/celery.sh b/compose/django/celery.sh index d1c4cf24..bf721204 100644 --- a/compose/django/celery.sh +++ b/compose/django/celery.sh @@ -2,6 +2,9 @@ LOGFILE="$LOGS_PATH/celery.log" +# wait for migrations +sleep 10 + exec /usr/local/bin/celery worker \ --app=hawc \ --loglevel=INFO \ diff --git a/compose/django/gunicorn.sh b/compose/django/gunicorn.sh index 1b689929..adb83287 100644 --- a/compose/django/gunicorn.sh +++ b/compose/django/gunicorn.sh @@ -1,9 +1,7 @@ #!/bin/sh -# make migrations python manage.py migrate --noinput python manage.py clear_cache -python manage.py build_d3_styles python manage.py collectstatic --noinput LOGFILE="$LOGS_PATH/gunicorn.log" diff --git a/docs/source/management_commands.rst b/docs/source/management_commands.rst index 4399ffba..41cbcafa 100644 --- a/docs/source/management_commands.rst +++ b/docs/source/management_commands.rst @@ -41,12 +41,6 @@ Assessment module commands psql -d hawc -f /path/to/export.sql -- ``build_d3_styles``: notes. Assemble all CSS styles used in d3 visualizations and create a new CSS file which can be inserted into static SVG files containing all the style information from external-style sheets. Used for statically generating svg visualizations with appropriate styles on server using Inkscape. - - Example usage:: - - $ python manage.py build_d3_styles - - ``clean_text``: notes. Clean field to remove control characters or other non-UTF-8 characters which can typically be added when users copy and paste from PDF documents. Example usage:: diff --git a/project/assessment/management/commands/build_d3_styles.py b/project/assessment/management/commands/build_d3_styles.py deleted file mode 100644 index 64bbac77..00000000 --- a/project/assessment/management/commands/build_d3_styles.py +++ /dev/null @@ -1,42 +0,0 @@ -import os -import re - -from django.core.management.base import BaseCommand, CommandError -from django.conf import settings - - -HELP_TEXT = """Assemble all CSS styles used in d3 visualizations and create a -new CSS file which can be inserted into static SVG files containing all the -style information from external-style sheets.""" - - -class Command(BaseCommand): - help = HELP_TEXT - - def handle(self, *args, **options): - static_path = os.path.abspath(os.path.join(settings.PROJECT_PATH, 'static')) - - def remove_spacing(txt, character): - txt = re.sub(character + ' ', character, txt) - return re.sub(' ' + character, character, txt) - - # Only using D3.css as adding other style-sheets with non SVG styles can - # potentially break the Inkscape SVG processor. - files = ('css/d3.css', ) - - txt = '' - for fn in files: - with open(os.path.join(static_path, fn), 'r') as f: - txt = txt + f.read() + ' ' - txt = re.sub(r'\/\*[^(\*\/)]+\*\/', ' ', txt) - txt = re.sub(r'\n', ' ', txt) - txt = re.sub(r' >', ' ', txt) # this style-type can break illustrator - txt = re.sub(r'[ ]+', ' ', txt) - txt = remove_spacing(txt, ":") - txt = remove_spacing(txt, "{") - txt = remove_spacing(txt, "}") - txt = remove_spacing(txt, ";") - txt = re.sub(r'}', r'}\n', txt) - - with open(os.path.join(static_path, 'css/hawc_d3_aggregated.css'), 'w+') as f: - f.write(txt) diff --git a/project/templates/rasterize.html b/project/templates/rasterize.html index d7172a78..973e5501 100644 --- a/project/templates/rasterize.html +++ b/project/templates/rasterize.html @@ -11,8 +11,8 @@ font-family: "Liberation Sans", Arial, Helvetica, sans-serif !important; } -{{css|safe}} +{{css|safe}} {% endblock %} {% block navbar_outer %} diff --git a/project/utils/svg.py b/project/utils/svg.py index f7080d16..e3f54274 100644 --- a/project/utils/svg.py +++ b/project/utils/svg.py @@ -1,4 +1,3 @@ -import codecs from datetime import datetime import base64 import logging @@ -21,22 +20,63 @@ logger = logging.getLogger(__name__) -def _get_css_styles(): - txt = '' - - path = os.path.join( - settings.PROJECT_PATH, r'static/css/hawc_d3_aggregated.css') - - if os.path.exists(path): - with codecs.open(path, 'r', 'UTF-8') as f: - txt = str(f.read()) - txt = r''.format(txt) # noqa - - return txt - - -# load CSS into memory upon runtime (only do it once) -D3_CSS_STYLES = _get_css_styles() +class HawcStyles: + + @property + def for_svg(self): + # lazy evaluation + style = getattr(self, '_for_svg', None) + if style is None: + style = ''.format(self._get_styles()) # noqa + setattr(self, '_for_svg', style) + return style + + @property + def for_html(self): + # lazy evaluation + style = getattr(self, '_for_html', None) + if style is None: + style = ''.format(self._get_styles()) # noqa + setattr(self, '_for_html', style) + return style + + def _get_styles(self): + + print("SLOW") + + def remove_spacing(txt, character): + txt = re.sub(character + ' ', character, txt) + return re.sub(' ' + character, character, txt) + + def get_styles(files): + # Only using D3.css as adding other style-sheets with non SVG + # styles can potentially break the SVG processor. + texts = [] + for fn in files: + with open(fn, 'r') as f: + texts.append(f.read()) + return ' '.join(texts) + + def compact(txt): + txt = re.sub(r'\/\*[^(\*\/)]+\*\/', ' ', txt) + txt = re.sub(r'\n', ' ', txt) + txt = re.sub(r' >', ' ', txt) # can break illustrator + txt = re.sub(r'[ ]+', ' ', txt) + txt = remove_spacing(txt, ':') + txt = remove_spacing(txt, '{') + txt = remove_spacing(txt, '}') + txt = remove_spacing(txt, ';') + txt = re.sub(r'}', r'}\n', txt) + return txt + + path = os.path.abspath(os.path.join(settings.PROJECT_PATH, 'static')) + files = ( + os.path.join(path, 'css/d3.css'), + ) + return compact(get_styles(files)) + + +Styles = HawcStyles() class SVGConverter(object): @@ -47,22 +87,27 @@ def __init__(self, svg, url, width, height): self.height = height self.tempfns = [] - svg = base64.b64decode(svg).decode('utf8').replace('%u', '\\u').encode().decode('unicode-escape') + svg = base64.b64decode(svg)\ + .decode('utf8')\ + .replace('%u', '\\u')\ + .encode()\ + .decode('unicode-escape') self.svg = parse.unquote(svg) def to_svg(self): - # add embedded styles svg = self.svg - # add CSS styles + # add CSS style definitions match = re.search(r']+>', svg) insertion_point = match.end() # Manually add our CSS styles from a file. Because there are problems # inserting CDATA using a python etree, we use a regex instead - svg = (svg[:insertion_point] + D3_CSS_STYLES + svg[insertion_point:]) - - return svg + return ''.join([ + svg[:insertion_point], + Styles.for_svg, + svg[insertion_point:] + ]) def _rasterize_png(self): # rasterize png and return filename @@ -184,7 +229,7 @@ def _to_html(self): request = HttpRequest() context = RequestContext(request, dict( svg=self.svg, - css=D3_CSS_STYLES + css=Styles.for_html, )) html = render_to_string('rasterize.html', context).encode('UTF-8') fn = self.get_tempfile(suffix='.html')