Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] master from lux-org:master #38

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
42 changes: 4 additions & 38 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,8 @@ jobs:
- uses: actions/setup-node@v1
with:
node-version: "12.x"
- run: npm install --save-dev @commitlint/{config-conventional,cli} commitlint-plugin-jira-rules commitlint-config-jira
- name: Add dependencies for commitlint action
run: echo "NODE_PATH=$GITHUB_WORKSPACE/node_modules" >> $GITHUB_ENV
- run: git remote add upstream https://github.com/lux-org/lux
- run: git fetch upstream
- run: npx commitlint --from upstream/master --to HEAD --verbose
pre-commit:
name: Check pre-commit hooks
runs-on: ubuntu-latest
Expand All @@ -40,51 +36,21 @@ jobs:

runs-on: ubuntu-latest

# Service containers to run with `container-job`
services:
# Label used to access the service container
postgres:
# Docker Hub image
image: postgres
# Provide the password for postgres
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: lux
POSTGRES_DB: postgres
# Set health checks to wait until postgres has started
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
ports:
- 5432:5432

steps:
- uses: actions/checkout@v2
- name: Set up Python 3.7
- name: Set up Python 3.10
uses: actions/setup-python@v2
with:
python-version: 3.7
python-version: 3.10.12
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install jupyter-client==6.1.6
pip install wheel
pip install -r requirements.txt
pip install -r requirements-dev.txt
pip install sqlalchemy

# pip uninstall -y lux-widget
# pip install git+git://github.com/lux-org/lux-widget.git
# # Temporary Fix (#372)
# cd /opt/hostedtoolcache/Python/3.7.10/x64/lib/python3.7/site-packages/luxwidget/
# mkdir labextension
# cd labextension
# wget https://raw.githubusercontent.com/lux-org/lux-widget/master/luxwidget/nbextension/package.json

- name: Upload data to Postgres
run: |
python lux/data/upload_car_data.py
python lux/data/upload_aug_test_data.py
python lux/data/upload_airbnb_nyc_data.py
- name: Test with Pytest and Code Coverage Report
run: |
pytest --cov-report term --cov=lux tests/ tests_sql/
bash <(curl -s https://codecov.io/bash)
pytest --cov-report term --cov=lux tests/
bash <(curl -s https://codecov.io/bash)
5 changes: 3 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
repos:
- repo: https://github.com/psf/black
rev: 20.8b1
rev: 22.3.0
hooks:
- id: black
- id: black
additional_dependencies: ['click==8.0.4']
6 changes: 3 additions & 3 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,16 @@
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

import subprocess

subprocess.call(["sh", "./docbuild.sh"])
import os

os.system("sh ./docbuild.sh")
# -- Path setup --------------------------------------------------------------

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys

sys.path.insert(0, os.path.abspath(".."))
Expand Down
51 changes: 48 additions & 3 deletions doc/source/guide/FAQ.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,42 @@ To troubleshoot your Lux installation, we recommend cloning `this repo <https://

The Lux Jupyter widget does not show up when I print a dataframe.
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
- If you recieve the output message :code:`LuxWidget(...)` but you do not see Lux widget show up, it is possible that the widget is not installed correctly. Run :code:`jupyter nbextension list` on the terminal, and you should see the following as one of the listed items.
To check if your luxwidget configuration is set up correctly, please run the following code in your notebook to debug:

.. code-block:: bash

import lux
lux.debug_info()

We recommend using a simple example to test if your widget is showing correctly:

.. code-block:: bash

import lux
import pandas as pd
df = pd.read_csv("https://raw.githubusercontent.com/lux-org/lux-datasets/master/data/college.csv")
df

If you receive the output message :code:`❌ IPython shell not available.`, please run your code in a notebook interface such as Jupyter notebook, Jupyter Lab, JupyterHub, or VSCode.

If you receive the output message :code:`❌ WARNING: luxwidget is not enabled in Jupyter Lab.`, run the following code in your terminal to enable luxwidget:

.. code-block:: bash

jupyter labextension install @jupyter-widgets/jupyterlab-manager
jupyter labextension install luxwidget

If you receive the output message :code:`❌ WARNING: luxwidget is not enabled in Jupyter Notebook.`, run the following code in your terminal to enable luxwidget:

.. code-block:: bash

jupyter nbextension install --py luxwidget
jupyter nbextension enable --py luxwidget


If the Lux Jupyter widget still does not show up, try the following:

- If you receive the output message :code:`LuxWidget(...)` but you do not see Lux widget show up, it is possible that the widget is not installed correctly. Run :code:`jupyter nbextension list` on the terminal, and you should see the following as one of the listed items.

.. code-block:: bash

Expand All @@ -116,6 +151,16 @@ The Lux Jupyter widget does not show up when I print a dataframe.
- If you are able to import lux successfully and you do not see the "Toggle button" when you print the dataframe, it may be possible that Lux is not compatible with your browser. Lux is compatible with Google Chrome, but have not been extensively tested on Safari or Firefox.
- If you recieve the error message :code:`A Jupyter widget could not be displayed because the widget state could not be found.` This could happen if the kernel storing the widget is no longer available, or if the widget state was not saved in the notebook. You may be able to create the widget by running the particular cell again. If this doesn't work, then you may want try restarting the notebook and rerun the cell.
- If you receive the error message :code:`ModuleNotFoundError: No module named 'luxwidget'`, it is possible that your luxwidget and lux-api versions are not in sync. The latest version of lux-api requires luxwidget v0.1 or above. Try running the following code:
.. code-block:: bash

pip uninstall lux-api
pip uninstall lux-widget
pip uninstall jupyterlab_widgets
pip install lux-api

jupyter labextension install @jupyter-widgets/jupyterlab-manager
jupyter labextension install luxwidget

- If you receive the error message :code:`PermissionError: [Errno 13] Permission denied.` during the execution of the command :code:`jupyter nbextension install --py luxwidget`, then you can add the flag :code:`--user` (:code:`jupyter nbextension enable --py --user luxwidget`).
- Alternatively, if none of the above works. You can try creating a fresh virtual environment and follow the `quick install instructions <https://github.com/lux-org/lux#installation>`_.

Expand All @@ -124,8 +169,8 @@ The Lux Jupyter widget does not show up when I print a dataframe.
pip uninstall lux-api
pip uninstall lux-widget

jupyter nbextension uninstall --py luxWidget
jupyter nbextension disable --py luxWidget
jupyter nbextension uninstall --py luxwidget
jupyter nbextension disable --py luxwidget

pip install lux-api

Expand Down
1 change: 1 addition & 0 deletions doc/source/reference/gen/lux._config.config.Config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
.. autosummary::

~Config.__init__
~Config.read_query_template
~Config.register_action
~Config.remove_action
~Config.set_SQL_connection
Expand Down
1 change: 1 addition & 0 deletions doc/source/reference/gen/lux.core.frame.LuxDataFrame.rst
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@
~LuxDataFrame.to_string
~LuxDataFrame.to_timestamp
~LuxDataFrame.to_xarray
~LuxDataFrame.to_xml
~LuxDataFrame.transform
~LuxDataFrame.transpose
~LuxDataFrame.truediv
Expand Down
1 change: 1 addition & 0 deletions doc/source/reference/gen/lux.core.series.LuxSeries.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
~LuxSeries.idxmax
~LuxSeries.idxmin
~LuxSeries.infer_objects
~LuxSeries.info
~LuxSeries.interpolate
~LuxSeries.isin
~LuxSeries.isna
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
~Executor.compute_data_model
~Executor.compute_data_model_lookup
~Executor.compute_data_type
~Executor.compute_dataset_metadata
~Executor.compute_stats
~Executor.execute
~Executor.execute_2D_binning
Expand Down
49 changes: 26 additions & 23 deletions lux/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import lux


class LuxDataFrame(pd.DataFrame):
class LuxDataFrameMixin:
"""
A subclass of pd.DataFrame that supports all dataframe operations while housing other variables and functions for generating visual recommendations.
"""
Expand Down Expand Up @@ -58,6 +58,8 @@ class LuxDataFrame(pd.DataFrame):
]

def __init__(self, *args, **kw):
super().__init__(*args, **kw)

self._history = History()
self._intent = []
self._inferred_intent = []
Expand All @@ -66,7 +68,6 @@ def __init__(self, *args, **kw):
self._current_vis = []
self._prev = None
self._widget = None
super(LuxDataFrame, self).__init__(*args, **kw)

self.table_name = ""
if lux.config.SQLconnection == "":
Expand All @@ -92,20 +93,6 @@ def __init__(self, *args, **kw):
self._type_override = {}
warnings.formatwarning = lux.warning_format

@property
def _constructor(self):
return LuxDataFrame

@property
def _constructor_sliced(self):
def f(*args, **kwargs):
s = LuxSeries(*args, **kwargs)
for attr in self._metadata: # propagate metadata
s.__dict__[attr] = getattr(self, attr, None)
return s

return f

@property
def history(self):
return self._history
Expand Down Expand Up @@ -174,23 +161,23 @@ def expire_metadata(self) -> None:
## Override Pandas ##
#####################
def __getattr__(self, name):
ret_value = super(LuxDataFrame, self).__getattr__(name)
ret_value = super().__getattr__(name)
self.expire_metadata()
self.expire_recs()
return ret_value

def _set_axis(self, axis, labels):
super(LuxDataFrame, self)._set_axis(axis, labels)
super()._set_axis(axis, labels)
self.expire_metadata()
self.expire_recs()

def _update_inplace(self, *args, **kwargs):
super(LuxDataFrame, self)._update_inplace(*args, **kwargs)
super()._update_inplace(*args, **kwargs)
self.expire_metadata()
self.expire_recs()

def _set_item(self, key, value):
super(LuxDataFrame, self)._set_item(key, value)
super()._set_item(key, value)
self.expire_metadata()
self.expire_recs()

Expand Down Expand Up @@ -847,13 +834,13 @@ def save_as_html(self, filename: str = "export.html", output=False):

# Overridden Pandas Functions
def head(self, n: int = 5):
ret_val = super(LuxDataFrame, self).head(n)
ret_val = super().head(n)
ret_val._prev = self
ret_val._history.append_event("head", n=5)
return ret_val

def tail(self, n: int = 5):
ret_val = super(LuxDataFrame, self).tail(n)
ret_val = super().tail(n)
ret_val._prev = self
ret_val._history.append_event("tail", n=5)
return ret_val
Expand All @@ -864,11 +851,27 @@ def groupby(self, *args, **kwargs):
history_flag = True
if "history" in kwargs:
del kwargs["history"]
groupby_obj = super(LuxDataFrame, self).groupby(*args, **kwargs)
groupby_obj = super().groupby(*args, **kwargs)
for attr in self._metadata:
groupby_obj.__dict__[attr] = getattr(self, attr, None)
if history_flag:
groupby_obj._history = groupby_obj._history.copy()
groupby_obj._history.append_event("groupby", *args, **kwargs)
groupby_obj.pre_aggregated = True
return groupby_obj


class LuxDataFrame(LuxDataFrameMixin, pd.DataFrame):
@property
def _constructor(self):
return LuxDataFrame

@property
def _constructor_sliced(self):
def f(*args, **kwargs):
s = LuxSeries(*args, **kwargs)
for attr in self._metadata: # propagate metadata
s.__dict__[attr] = getattr(self, attr, None)
return s

return f
Loading