Skip to content

Commit

Permalink
Merge branch 'main' into add_limit_bounds
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr authored Oct 31, 2023
2 parents ba16523 + 592e75b commit f6d943e
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 24 deletions.
20 changes: 5 additions & 15 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,11 @@ concurrency:

jobs:
pre_commit:
name: Run pre-commit hooks
name: Run pre-commit
runs-on: 'ubuntu-latest'
steps:
- uses: actions/checkout@v3
with:
fetch-depth: "1"
- name: set PY
run: echo "PY=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV
- uses: actions/cache@v3
with:
path: ~/.cache/pre-commit
key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }}
- name: pre-commit
uses: pre-commit/[email protected]
test_suite:
- uses: holoviz-dev/holoviz_tasks/[email protected]
unit_test_suite:
name: Pytest on ${{ matrix.python-version }}, ${{ matrix.os }}
needs: [pre_commit]
runs-on: ${{ matrix.os }}
Expand All @@ -47,9 +37,9 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:

- uses: holoviz-dev/holoviz_tasks/install@v0.1a15
- uses: holoviz-dev/holoviz_tasks/install@v0.1a18
with:
name: test_suite
name: unit_test_suite
python-version: ${{ matrix.python-version }}
channel-priority: flexible
channels: pyviz/label/dev,bokeh,conda-forge,nodefaults
Expand Down
11 changes: 9 additions & 2 deletions lumen/filters/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,13 @@ class Filter(MultiTypeComponent):

def __init__(self, **params):
super().__init__(**params)
if state.config and state.config.sync_with_url and self.sync_with_url and pn.state.location:
if self._sync_with_url:
pn.state.location.sync(self, {'value': self.field}, on_error=self._url_sync_error)

@property
def _sync_with_url(self) -> bool:
return bool(state.config and state.config.sync_with_url and self.sync_with_url and pn.state.location)

@classproperty
def _required_keys(cls) -> List[str | Tuple[str, ...]]: # type: ignore
return ['field'] if cls._requires_field else []
Expand Down Expand Up @@ -313,8 +317,11 @@ def __init__(self, **params):
self.widget.name = self.label
self.widget.visible = self.visible
self.widget.disabled = self.disabled
val = self.value
self.widget.link(self, bidirectional=True, value='value', visible='visible', disabled='disabled')
if self.default is not None:
if val is not None:
self.widget.value = val
elif self.default is not None:
self.widget.value = self.default

@classmethod
Expand Down
18 changes: 18 additions & 0 deletions lumen/tests/sample_dashboard/sync_query_filters_default.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
config:
sync_with_url: true
sources:
test:
type: 'file'
files: ['../sources/test.csv']
targets:
- title: "Test"
source: test
filters:
- type: widget
field: A
- type: widget
field: C
default: ['foo1']
views:
- table: test
type: test
13 changes: 9 additions & 4 deletions lumen/tests/sources/test_duckdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def duckdb_source():
f"SET home_directory='{root}';"
],
root=root,
sql_expr='SELECT A, B, C, D::TIMESTAMP AS D FROM {table}',
sql_expr='SELECT A, B, C, D::TIMESTAMP_NS AS D FROM {table}',
tables={
'test_sql': f"sqlite_scan('{root + '/test.db'}', 'mixed')",
'test_sql_with_none': f"sqlite_scan('{root + '/test.db'}', 'mixed_none')",
Expand Down Expand Up @@ -81,23 +81,28 @@ def test_duckdb_get_schema(duckdb_source):
'type': 'string'
}
}
assert duckdb_source.get_schema('test_sql') == expected_sql
source = duckdb_source.get_schema('test_sql')
source["C"]["enum"].sort()
assert source == expected_sql
assert list(duckdb_source._schema_cache.keys()) == ['test_sql']


def test_duckdb_get_schema_with_none(duckdb_source):
enum = ['foo1', None, 'foo3', 'foo5']
expected_sql = {
'A': {'inclusiveMaximum': 4.0, 'inclusiveMinimum': 0.0, 'type': 'number'},
'B': {'inclusiveMaximum': 1.0, 'inclusiveMinimum': 0.0, 'type': 'number'},
'C': {'enum': ['foo1', np.nan, 'foo3', 'foo5'], 'type': 'string'},
'C': {'enum': enum, 'type': 'string'},
'D': {
'format': 'datetime',
'inclusiveMaximum': '2009-01-07 00:00:00',
'inclusiveMinimum': '2009-01-01 00:00:00',
'type': 'string'
}
}
assert duckdb_source.get_schema('test_sql_with_none') == expected_sql
source = duckdb_source.get_schema('test_sql_with_none')
source["C"]["enum"].sort(key=enum.index)
assert source == expected_sql
assert list(duckdb_source._schema_cache.keys()) == ['test_sql_with_none']


Expand Down
31 changes: 31 additions & 0 deletions lumen/tests/test_dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,37 @@ def test_dashboard_with_url_sync_filters(set_root, document):
pn.state.location.search = '?A=%5B0.3%2C+0.8%5D&C=%5B%22foo1%22%2C+%22foo2%22%2C+%22foo3%22%5D'
assert f2.value == ['foo1', 'foo2', 'foo3']

def test_dashboard_with_url_sync_filters_with_default(set_root, document):
root = pathlib.Path(__file__).parent / 'sample_dashboard'
set_root(str(root))
dashboard = Dashboard(str(root / 'sync_query_filters_default.yaml'))
dashboard._render_dashboard()
layout = dashboard.layouts[0]
f1, f2 = list(layout._pipelines.values())[0].filters
f1.value = (0.1, 0.7)
assert pn.state.location.search == '?C=%5B%27foo1%27%5D&A=%5B0.1%2C+0.7%5D'
pn.state.location.search = '?A=%5B0.3%2C+0.8%5D'
assert f1.value == (0.3, 0.8)
assert f2.value == ['foo1']
assert f1.widget.value == (0.3, 0.8)
assert f2.widget.value == ['foo1']
f2.value = ['foo1', 'foo2']
assert pn.state.location.search == '?A=%5B0.3%2C+0.8%5D&C=%5B%22foo1%22%2C+%22foo2%22%5D'
pn.state.location.search = '?A=%5B0.3%2C+0.8%5D&C=%5B%22foo1%22%2C+%22foo2%22%2C+%22foo3%22%5D'
assert f2.value == ['foo1', 'foo2', 'foo3']
assert f2.widget.value == ['foo1', 'foo2', 'foo3']

def test_dashboard_with_url_sync_filters_with_overwritten_default(set_root, document):
root = pathlib.Path(__file__).parent / 'sample_dashboard'
set_root(str(root))
dashboard = Dashboard(str(root / 'sync_query_filters_default.yaml'))
dashboard._render_dashboard()
layout = dashboard.layouts[0]
f1, f2 = list(layout._pipelines.values())[0].filters
f1.value = (0.1, 0.7)
f2.value = [] # overwriting default with empty list
assert pn.state.location.search == '?C=%5B%5D&A=%5B0.1%2C+0.7%5D'
assert f2.widget.value == []

@sql_available
def test_dashboard_with_sql_source_and_transforms(set_root, document, mixed_df_object_type):
Expand Down
4 changes: 4 additions & 0 deletions lumen/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import bokeh
import pandas as pd
import panel as pn
import param

from jinja2 import DebugUndefined, Environment, Undefined
from packaging.version import Version
Expand All @@ -25,6 +26,9 @@
log = getLogger(__name__)

bokeh3 = Version(bokeh.__version__) > Version("3.0")
param2 = Version(param.__version__) > Version("2.0rc1")

disallow_refs = {'allow_refs': False} if param2 else {}

VARIABLE_RE = re.compile(r'\$variables\.([a-zA-Z_]\w*)')

Expand Down
5 changes: 3 additions & 2 deletions lumen/variables/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

from ..base import MultiTypeComponent
from ..state import state
from ..util import is_ref, resolve_module_reference
from ..util import disallow_refs, is_ref, resolve_module_reference

if TYPE_CHECKING:
from panel.viewable import Viewable
Expand Down Expand Up @@ -378,7 +378,8 @@ class Parameter(Variable):
`Parameter` variables reflect the current value of a parameter.
"""

parameter = param.ClassSelector(class_=param.Parameter, constant=True, doc="""
parameter = param.ClassSelector(class_=param.Parameter, constant=True,
**disallow_refs, doc="""
A parameter instance whose current value will be reflected
on this variable.""")

Expand Down
2 changes: 1 addition & 1 deletion lumen/views/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def __panel__(self) -> Viewable:
return pn.panel(pn.bind(lambda e: self.panel, self.param.rerender))

def _update_loading(self, event):
if self._panel is not None:
if hasattr(self._panel, 'loading'):
with immediate_dispatch():
self._panel.loading = event.new

Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def get_setup_version(reponame):
'codecov',
'pre-commit',
'matplotlib >=3.4', # Ubuntu + Python 3.9 installs old version matplotlib (3.3.2)
'pytest-github-actions-annotate-failures',
],
'doc': [
'nbsite >=0.8.2',
Expand Down

0 comments on commit f6d943e

Please sign in to comment.