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

Improve Download with Index and Filename parameters #438

Merged
merged 4 commits into from
Feb 2, 2023
Merged
Show file tree
Hide file tree
Changes from 3 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
23 changes: 23 additions & 0 deletions lumen/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import os
import re
import sys
import unicodedata

from functools import wraps
from logging import getLogger
Expand Down Expand Up @@ -314,3 +315,25 @@ def wrapper(*args, **kwargs):
return decorator(function)

return decorator


def slugify(value, allow_unicode=False) -> str:
"""
Convert to ASCII if 'allow_unicode' is False. Convert spaces or repeated
dashes to single dashes. Remove characters that aren't alphanumerics,
underscores, or hyphens. Convert to lowercase. Also strip leading and
trailing whitespace, dashes, and underscores.

From: https://docs.djangoproject.com/en/4.0/_modules/django/utils/text/#slugify
"""
value = str(value)
if allow_unicode:
value = unicodedata.normalize("NFKC", value)
else:
value = (
unicodedata.normalize("NFKD", value)
.encode("ascii", "ignore")
.decode("ascii")
)
value = re.sub(r"[^\w\s-]", "", value.lower())
return re.sub(r"[-\s]+", "-", value).strip("-_")
29 changes: 21 additions & 8 deletions lumen/views/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from ..transforms.base import Transform
from ..transforms.sql import SQLTransform
from ..util import (
VARIABLE_RE, catch_and_notify, is_ref, resolve_module_reference,
VARIABLE_RE, catch_and_notify, is_ref, resolve_module_reference, slugify,
)
from ..validation import ValidationError

Expand All @@ -52,12 +52,21 @@ class Download(Component, Viewer):
color = param.Color(default='grey', allow_None=True, doc="""
The color of the download button.""")

hide = param.Boolean(default=False, doc="""
Whether the download button hides when not in focus.""")
filename = param.String(default=None, doc="""filenamefil
The filename of the downloaded table.
File extension is added automatic based on the format.
If filename is not added, it will be based on the name of the view.
""")

format = param.ObjectSelector(default=None, objects=DOWNLOAD_FORMATS, doc="""
The format to download the data in.""")

hide = param.Boolean(default=False, doc="""
Whether the download button hides when not in focus.""")

index = param.Boolean(default=True, doc="""
Whether the downloaded table has an index.""")

kwargs = param.Dict(default={}, doc="""
Keyword arguments passed to the serialization function, e.g.
data.to_csv(file_obj, **kwargs).""")
Expand Down Expand Up @@ -89,18 +98,22 @@ def _table_data(self) -> IO:
io = BytesIO()
data = self.view.get_data()
if self.format == 'csv':
data.to_csv(io, **self.kwargs)
data.to_csv(io, index=self.index, **self.kwargs)
elif self.format == 'json':
data.to_json(io, **self.kwargs)
data.to_json(io, index=self.index, **self.kwargs)
elif self.format == 'xlsx':
data.to_excel(io, **self.kwargs)
data.to_excel(io, index=self.index, **self.kwargs)
elif self.format == 'parquet':
data.to_parquet(io, **self.kwargs)
data.to_parquet(io, index=self.index, **self.kwargs)
io.seek(0)
return io

def __panel__(self) -> DownloadButton:
filename = f'{self.view.pipeline.table}.{self.format}'
if self.filename:
filename = self.filename
else:
filename = slugify(self.view.title or self.view.pipeline.table)
filename = f'{filename}.{self.format}'
return DownloadButton(
callback=self._table_data, filename=filename, color=self.color,
size=18, hide=self.hide
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def get_setup_version(reponame):
'sql': [
'duckdb',
'intake-sql',
'sqlalchemy <2', # Don't work with pandas yet
],
'tests': [
'pytest',
Expand Down