From c1a03c411f71be90eeb5a94c32665682fd09c7ce Mon Sep 17 00:00:00 2001 From: gggordon Date: Sun, 15 Oct 2017 23:13:38 -0500 Subject: [PATCH 1/4] Python 3 Compatible --- LICENSE | 1 + src/gleam/__init__.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index d9b1fe4..39d479f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,7 @@ The MIT License (MIT) Copyright (c) 2014 David Robinson +Copyright (c) 2017 G Gordon Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/gleam/__init__.py b/src/gleam/__init__.py index d10829a..2c00548 100644 --- a/src/gleam/__init__.py +++ b/src/gleam/__init__.py @@ -4,7 +4,6 @@ import os import json -import urlparse from collections import namedtuple from flask import Flask, request, send_from_directory @@ -19,6 +18,7 @@ class InputData(object): class Page(object): + @classmethod def add_flask(cls, app, path="/"): """Add this page to a Flask application at the given path""" From d7c5d5b5f772eac333d1e6cdec2a691d6545fe63 Mon Sep 17 00:00:00 2001 From: gggordon Date: Sun, 15 Oct 2017 23:14:20 -0500 Subject: [PATCH 2/4] Python 3 Compatible. No longer saves images files to static directory. Temporary in memory images used --- src/gleam/panels.py | 78 +++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 35 deletions(-) diff --git a/src/gleam/panels.py b/src/gleam/panels.py index bc0c494..372d7f8 100644 --- a/src/gleam/panels.py +++ b/src/gleam/panels.py @@ -1,6 +1,8 @@ from jinja2 import Environment, PackageLoader import os +import io import hashlib +import base64 import random import wtforms @@ -43,10 +45,10 @@ def form_class(self): class InputForm(Form): extra = wtforms.fields.HiddenField() - # get the fields - for name, obj in self.__class__.__dict__.iteritems(): - if isinstance(obj, UnboundField): - setattr(InputForm, name, obj) + # get the fiel + for name in self.__class__.__dict__: + if isinstance(getattr(self,name),UnboundField): + setattr(InputForm,name,getattr(self,name)) return InputForm @@ -73,7 +75,7 @@ class PlotPanel(Panel): template_name = "plot.html" width = 700 height = 500 - plotter = "ggplot" + plotter = "matplotlib" extension = "png" name = "plot" @@ -82,9 +84,9 @@ def __init__(self): self.values["height"] = self.height self.values["width"] = self.width self.values["name"] = self.name - self.plot_dir = os.path.join("static", "figures", self.name) - if not os.path.exists(self.plot_dir): - os.makedirs(self.plot_dir) + #self.plot_dir = os.path.join("static", "figures", self.name) + #if not os.path.exists(self.plot_dir): + # os.makedirs(self.plot_dir) def __call__(self, func): """Using as a decorator""" @@ -94,35 +96,41 @@ def __call__(self, func): def refresh(self, data): """Generate a new image, then tell the page to change the src""" - h = hashlib.md5(str(data.__dict__)).hexdigest() - print h - - outfile = os.path.join(self.plot_dir, h + "." + self.extension) - - if not os.path.exists(outfile): - - if self.plotter == "custom": - kwargs["__outfile"] = outfile - - if self.plotter == "matplotlib": - from matplotlib import pyplot as plt - plt.clf() - - ret = self.plot(data) - if ret is None: - # don't change the plot at all - return {self.name: {}} - - # after - if self.plotter == "matplotlib": - plt.savefig(outfile) - elif self.plotter == "ggplot": - from ggplot.utils import ggsave - ggsave(outfile, ret) + #cchane + + if self.plotter == "custom": + kwargs["__outfile"] = outfile + + if self.plotter == "matplotlib": + from matplotlib import pyplot as plt + plt.clf() + + ret = self.plot(data) + if ret is None: + # don't change the plot at all + return {self.name: {}} + + # after + tempFile = io.BytesIO() + + if self.plotter == "matplotlib": + + plt.savefig(tempFile,format="png") + + + elif self.plotter == "ggplot": + from ggplot.utils import ggsave + + ggsave(tempFile, ret) + tempFile.seek(0) + base64encodedimage = base64.b64encode(tempFile.getvalue()).decode('utf8') # turn into a URL, add a dummy param to avoid browser caching - url = outfile.replace(os.path.sep, "/") - url = url + "?dummy=" + str(random.random()) + tempFile.seek(0) + base64encodedimage = base64.b64encode(tempFile.getvalue()).decode('utf8') + tempFile.close() + + url = 'data:image/png;base64,'+ base64encodedimage return {self.name: {"src": url}} From a622b7fb56e60096ee983f427cabc4b3a6634d5b Mon Sep 17 00:00:00 2001 From: gggordon Date: Sun, 15 Oct 2017 23:21:19 -0500 Subject: [PATCH 3/4] GGplot save fix --- src/gleam/panels.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gleam/panels.py b/src/gleam/panels.py index 372d7f8..eb17c24 100644 --- a/src/gleam/panels.py +++ b/src/gleam/panels.py @@ -121,7 +121,8 @@ def refresh(self, data): elif self.plotter == "ggplot": from ggplot.utils import ggsave - ggsave(tempFile, ret) + #ggsave(tempFile, ret) + ret.save(tempFile) tempFile.seek(0) base64encodedimage = base64.b64encode(tempFile.getvalue()).decode('utf8') From 26c06c865e65c43581dd74ed3a9f8bcbf29ee295 Mon Sep 17 00:00:00 2001 From: gggordon Date: Sun, 15 Oct 2017 23:27:07 -0500 Subject: [PATCH 4/4] Updated version number --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 01e7487..8efcf58 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ author="David Robinson", author_email="dgrtwo@princeton.edu", description="Interactive visualization in Python", - version="0.1.2", + version="0.1.3", packages=["gleam"], package_dir={"gleam": "src/gleam"}, package_data={"gleam": [os.path.join("templates", "*"),