Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
include README.md
include LICENSE

recursive-include qgridjs *.*
recursive-include qgrid/qgridjs *.*
recursive-include qgrid/templates *.*
156 changes: 0 additions & 156 deletions qgrid.py

This file was deleted.

25 changes: 25 additions & 0 deletions qgrid/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from .grid import SlickGrid


def show_grid(data_frame, remote_js=False):
return SlickGrid(data_frame, remote_js)


def nbinstall(overwrite=False):
"""
"""
# Lazy imports so we don't pollute the namespace.
import os
from IPython.html.nbextensions import install_nbextension

qgridjs_path = os.path.join(
os.path.dirname(__file__),
'qgridjs',
)

install_nbextension(
qgridjs_path,
overwrite=overwrite,
symlink=False,
verbose=0,
)
83 changes: 83 additions & 0 deletions qgrid/grid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import pandas as pd
import numpy as np
import os
import uuid
import json

from IPython.display import display_html, display_javascript


def template_contents(filename):
template_filepath = os.path.join(
os.path.dirname(__file__),
'templates',
filename,
)
with open(template_filepath) as f:
return f.read()


SLICK_GRID_CSS = template_contents('slickgrid.css.template')
SLICK_GRID_JS = template_contents('slickgrid.js.template')


class SlickGrid(object):

def __init__(self, data_frame, remote_js=False):
self.data_frame = data_frame
self.remote_js = remote_js
self.div_id = str(uuid.uuid4())

self.df_copy = data_frame.copy()

if type(self.df_copy.index) == pd.core.index.MultiIndex:
self.df_copy.reset_index(inplace=True)
else:
self.df_copy.insert(0, self.df_copy.index.name, self.df_copy.index)

tc = dict(np.typecodes)
for key in np.typecodes.keys():
if "All" in key:
del tc[key]

self.column_types = []
for col_name, dtype in self.df_copy.dtypes.iteritems():
column_type = {'field': col_name}
for type_name, type_codes in tc.items():
if dtype.kind in type_codes:
column_type['type'] = type_name
break
self.column_types.append(column_type)

self.precision = pd.get_option('display.precision') - 1

def _ipython_display_(self):
try:
column_types_json = json.dumps(self.column_types)
data_frame_json = self.df_copy.to_json(
orient='records',
date_format='iso',
double_precision=self.precision,
)

if self.remote_js:
cdn_base_url = \
"https://rawgit.com/quantopian/qgrid/master/qgrid/qgridjs"
else:
cdn_base_url = "/nbextensions/qgridjs"

raw_html = SLICK_GRID_CSS.format(
div_id=self.div_id,
cdn_base_url=cdn_base_url,
)
raw_js = SLICK_GRID_JS.format(
cdn_base_url=cdn_base_url,
div_id=self.div_id,
data_frame_json=data_frame_json,
column_types_json=column_types_json,
)

display_html(raw_html, raw=True)
display_javascript(raw_js, raw=True)
except Exception as err:
display_html('ERROR: {}'.format(str(err)), raw=True)
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
13 changes: 13 additions & 0 deletions qgrid/templates/slickgrid.css.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<script type="text/javascript">
if ($("#dg-css").length == 0){{
$("head").append([
"<link href='{cdn_base_url}/lib/slick.grid.css' rel='stylesheet'>",
"<link href='{cdn_base_url}/lib/slick-default-theme.css' rel='stylesheet'>",
"<link href='http://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.4/css/jquery-ui.min.css' rel='stylesheet'>",
"<link id='dg-css' href='{cdn_base_url}/qgrid.css' rel='stylesheet'>"
]);
}}
</script>
<div class='q-grid-container'>
<div id='{div_id}' class='q-grid'></div>
</div>
48 changes: 48 additions & 0 deletions qgrid/templates/slickgrid.js.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
var path_dictionary = {{
jquery_drag: "{cdn_base_url}/lib/jquery.event.drag-2.2",
slick_core: "{cdn_base_url}/lib/slick.core.2.2",
slick_data_view: "{cdn_base_url}/lib/slick.dataview.2.2",
slick_grid: "{cdn_base_url}/lib/slick.grid.2.2",
data_grid: "{cdn_base_url}/qgrid",
date_filter: "{cdn_base_url}/qgrid.datefilter",
slider_filter: "{cdn_base_url}/qgrid.sliderfilter",
filter_base: "{cdn_base_url}/qgrid.filterbase",
handlebars: "https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/2.0.0/handlebars.min"
}};

var existing_config = require.s.contexts._.config;
if (!existing_config.paths['underscore']){{
path_dictionary['underscore'] = "https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min";
}}

if (!existing_config.paths['moment']){{
path_dictionary['moment'] = "https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.3/moment.min";
}}

if (!existing_config.paths['jqueryui']){{
path_dictionary['jqueryui'] = "https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.min";
}}

require.config({{
paths: path_dictionary
}});

if (typeof jQuery === 'function') {{
define('jquery', function() {{ return jQuery; }});
}}

require([
'jquery',
'jquery_drag',
'slick_core',
'slick_data_view'
],
function($){{
$('#{div_id}').closest('.rendered_html').removeClass('rendered_html');
require(['slick_grid'], function(){{
require(["data_grid"], function(dgrid){{
var grid = new dgrid.QGrid('#{div_id}', {data_frame_json}, {column_types_json});
grid.initialize_slick_grid();
}});
}});
}});
12 changes: 5 additions & 7 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,15 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
from setuptools import setup, find_packages
from setuptools import setup

setup(
name='qgrid',
version='0.1.0',
description='An extension for viewing pandas DataFrames in IPython notebook.',
description='A Pandas DataFrame viewer for IPython Notebook.',
author='Quantopian Inc.',
author_email='tshawver@quantopian.com',
packages=['qgridjs'],
py_modules = ['qgrid'],
packages=['qgrid'],
license='Apache 2.0',
include_package_data=True,
zip_safe=False,
Expand All @@ -38,11 +36,11 @@
'Intended Audience :: Science/Research',
'Topic :: Office/Business :: Financial',
'Topic :: Scientific/Engineering :: Information Analysis',
'Topic :: System :: Distributed Computing',
],
install_requires=[
'numpy',
'pandas'
'pandas',
'ipython[notebook]',
],
url="https://github.com/quantopian/qgrid"
)