Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from 12 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- [#854](https://github.com/plotly/dash-core-components/pull/854) Used `persistenceTransforms` to strip the time part of the datetime in the persited props of DatePickerSingle (date) and DatePickerRange (end_date, start_date), fixing [dcc#700](https://github.com/plotly/dash-core-components/issues/700).

### Added
- [#863](https://github.com/plotly/dash-core-components/pull/863) Added new `Download` component.
- [#850](https://github.com/plotly/dash-core-components/pull/850) Add property `prependData` to `Graph` to support `Plotly.prependTraces`
+ refactored the existing `extendTraces` API to be a single `mergeTraces` API that can handle both `prepend` as well as `extend`.

Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export(dccConfirmDialog)
export(dccConfirmDialogProvider)
export(dccDatePickerRange)
export(dccDatePickerSingle)
export(dccDownload)
export(dccDropdown)
export(dccGraph)
export(dccInput)
Expand Down
223 changes: 120 additions & 103 deletions dash_core_components_base/__init__.py
Original file line number Diff line number Diff line change
@@ -1,135 +1,152 @@
from __future__ import print_function as _
from ._imports_ import * # noqa: F401, F403
from ._imports_ import __all__ # noqa: E402
from .express import * # noqa: F401, F403

import json
import os as _os
import sys as _sys
import dash as _dash

_basepath = _os.path.dirname(__file__)
_filepath = _os.path.abspath(_os.path.join(_basepath, 'package-info.json'))
_filepath = _os.path.abspath(_os.path.join(_basepath, "package-info.json"))
with open(_filepath) as f:
package = json.load(f)

package_name = package['name'].replace(' ', '_').replace('-', '_')
__version__ = package['version']
package_name = package["name"].replace(" ", "_").replace("-", "_")
__version__ = package["version"]

# Module imports trigger a dash.development import, need to check this first
if not hasattr(_dash, 'development'):
print("Dash was not successfully imported. Make sure you don't have a file "
"named \n'dash.py' in your current directory.", file=_sys.stderr)
if not hasattr(_dash, "development"):
print(
"Dash was not successfully imported. Make sure you don't have a file "
"named \n'dash.py' in your current directory.",
file=_sys.stderr,
)
_sys.exit(1)

# Must update to dash>=0.23.1 to use this version of dash-core-components
if not hasattr(_dash.development.base_component, '_explicitize_args'):
print("Please update the `dash` module to >= 0.23.1 to use this "
"version of dash_core_components.\n"
"You are using version {:s}".format(_dash.version.__version__),
file=_sys.stderr)
if not hasattr(_dash.development.base_component, "_explicitize_args"):
print(
"Please update the `dash` module to >= 0.23.1 to use this "
"version of dash_core_components.\n"
"You are using version {:s}".format(_dash.version.__version__),
file=_sys.stderr,
)
_sys.exit(1)

from ._imports_ import * # noqa: F401, F403
from ._imports_ import __all__ # noqa: E402

_current_path = _os.path.dirname(_os.path.abspath(__file__))


_this_module = _sys.modules[__name__]

async_resources = [
'datepicker',
'dropdown',
'graph',
'highlight',
'markdown',
'slider',
'upload'
"datepicker",
"dropdown",
"graph",
"highlight",
"markdown",
"slider",
"upload",
]

_js_dist = []

_js_dist.extend([{
'relative_package_path': 'async-{}.js'.format(async_resource),
'external_url': (
'https://unpkg.com/dash-core-components@{}'
'/dash_core_components/async-{}.js'
).format(__version__, async_resource),
'namespace': 'dash_core_components',
'async': True
} for async_resource in async_resources])
_js_dist.extend(
[
{
"relative_package_path": "async-{}.js".format(async_resource),
"external_url": (
"https://unpkg.com/dash-core-components@{}"
"/dash_core_components/async-{}.js"
).format(__version__, async_resource),
"namespace": "dash_core_components",
"async": True,
}
for async_resource in async_resources
]
)

_js_dist.extend([{
'relative_package_path': 'async-{}.js.map'.format(async_resource),
'external_url': (
'https://unpkg.com/dash-core-components@{}'
'/dash_core_components/async-{}.js.map'
).format(__version__, async_resource),
'namespace': 'dash_core_components',
'dynamic': True
} for async_resource in async_resources])
_js_dist.extend(
[
{
"relative_package_path": "async-{}.js.map".format(async_resource),
"external_url": (
"https://unpkg.com/dash-core-components@{}"
"/dash_core_components/async-{}.js.map"
).format(__version__, async_resource),
"namespace": "dash_core_components",
"dynamic": True,
}
for async_resource in async_resources
]
)

_js_dist.extend([
{
'relative_package_path': '{}.min.js'.format(__name__),
'external_url': (
'https://unpkg.com/dash-core-components@{}'
'/dash_core_components/dash_core_components.min.js'
).format(__version__),
'namespace': 'dash_core_components'
},
{
'relative_package_path': '{}.min.js.map'.format(__name__),
'external_url': (
'https://unpkg.com/dash-core-components@{}'
'/dash_core_components/dash_core_components.min.js.map'
).format(__version__),
'namespace': 'dash_core_components',
'dynamic': True
},
{
'relative_package_path': '{}-shared.js'.format(__name__),
'external_url': (
'https://unpkg.com/dash-core-components@{}'
'/dash_core_components/dash_core_components-shared.js'
).format(__version__),
'namespace': 'dash_core_components'
},
{
'relative_package_path': '{}-shared.js.map'.format(__name__),
'external_url': (
'https://unpkg.com/dash-core-components@{}'
'/dash_core_components/dash_core_components-shared.js.map'
).format(__version__),
'namespace': 'dash_core_components',
'dynamic': True
},
{
'relative_package_path': 'plotly.min.js',
'external_url': (
'https://unpkg.com/dash-core-components@{}'
'/dash_core_components/plotly.min.js'
).format(__version__),
'namespace': 'dash_core_components',
'async': 'eager'
},
{
'relative_package_path': 'async-plotlyjs.js',
'external_url': (
'https://unpkg.com/dash-core-components@{}'
'/dash_core_components/async-plotlyjs.js'
).format(__version__),
'namespace': 'dash_core_components',
'async': 'lazy'
},
{
'relative_package_path': 'async-plotlyjs.js.map',
'external_url': (
'https://unpkg.com/dash-core-components@{}'
'/dash_core_components/async-plotlyjs.js.map'
).format(__version__),
'namespace': 'dash_core_components',
'dynamic': True
},
])
_js_dist.extend(
[
{
"relative_package_path": "{}.min.js".format(__name__),
"external_url": (
"https://unpkg.com/dash-core-components@{}"
"/dash_core_components/dash_core_components.min.js"
).format(__version__),
"namespace": "dash_core_components",
},
{
"relative_package_path": "{}.min.js.map".format(__name__),
"external_url": (
"https://unpkg.com/dash-core-components@{}"
"/dash_core_components/dash_core_components.min.js.map"
).format(__version__),
"namespace": "dash_core_components",
"dynamic": True,
},
{
"relative_package_path": "{}-shared.js".format(__name__),
"external_url": (
"https://unpkg.com/dash-core-components@{}"
"/dash_core_components/dash_core_components-shared.js"
).format(__version__),
"namespace": "dash_core_components",
},
{
"relative_package_path": "{}-shared.js.map".format(__name__),
"external_url": (
"https://unpkg.com/dash-core-components@{}"
"/dash_core_components/dash_core_components-shared.js.map"
).format(__version__),
"namespace": "dash_core_components",
"dynamic": True,
},
{
"relative_package_path": "plotly.min.js",
"external_url": (
"https://unpkg.com/dash-core-components@{}"
"/dash_core_components/plotly.min.js"
).format(__version__),
"namespace": "dash_core_components",
"async": "eager",
},
{
"relative_package_path": "async-plotlyjs.js",
"external_url": (
"https://unpkg.com/dash-core-components@{}"
"/dash_core_components/async-plotlyjs.js"
).format(__version__),
"namespace": "dash_core_components",
"async": "lazy",
},
{
"relative_package_path": "async-plotlyjs.js.map",
"external_url": (
"https://unpkg.com/dash-core-components@{}"
"/dash_core_components/async-plotlyjs.js.map"
).format(__version__),
"namespace": "dash_core_components",
"dynamic": True,
},
]
)

for _component in __all__:
setattr(locals()[_component], '_js_dist', _js_dist)
setattr(locals()[_component], "_js_dist", _js_dist)
106 changes: 106 additions & 0 deletions dash_core_components_base/express.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import io
import ntpath
import base64


# region Utils for Download component


def send_file(path, filename=None, type=None):
"""
Convert a file into the format expected by the Download component.
:param path: path to the file to be sent
:param filename: name of the file, if not provided the original filename is used
:param type: type of the file (optional, passed to Blob in the javascript layer)
:return: dict of file content (base64 encoded) and meta data used by the Download component
"""
# If filename is not set, read it from the path.
if filename is None:
filename = ntpath.basename(path)
# Read the file into a base64 string.
with open(path, "rb") as f:
content = base64.b64encode(f.read()).decode()
# Wrap in dict.
return dict(content=content, filename=filename, type=type, base64=True)


def send_bytes(writer, filename, type=None, **kwargs):
"""
Convert data written to BytesIO into the format expected by the Download component.
:param writer: a writer that can write to BytesIO
:param filename: the name of the file
:param type: type of the file (optional, passed to Blob in the javascript layer)
:return: dict of data frame content (base64 encoded) and meta data used by the Download component
"""
return _send_data_io(io.BytesIO(), False, writer, filename, type, **kwargs)


def send_string(writer, filename, type=None, **kwargs):
"""
Convert data written to StringIO into the format expected by the Download component.
:param writer: a writer that can write to StringIO
:param filename: the name of the file
:param type: type of the file (optional, passed to Blob in the javascript layer)
:return: dict of data frame content (base64 encoded) and meta data used by the Download component
"""
return _send_data_io(io.StringIO(), True, writer, filename, type, **kwargs)


def send_data_frame(writer, filename, type=None, **kwargs):
"""
Convert data frame into the format expected by the Download component.
:param writer: a data frame writer
:param filename: the name of the file
:param type: type of the file (optional, passed to Blob in the javascript layer)
:return: dict of data frame content (base64 encoded) and meta data used by the Download component

Examples
--------

>>> df = pd.DataFrame({'a': [1, 2, 3, 4], 'b': [2, 1, 5, 6], 'c': ['x', 'x', 'y', 'y']})
...
>>> send_data_frame(df.to_csv, "mydf.csv") # download as csv
>>> send_data_frame(df.to_json, "mydf.json") # download as json
>>> send_data_frame(df.to_excel, "mydf.xls", index=False) # download as excel
>>> send_data_frame(df.to_pkl, "mydf.pkl") # download as pickle

"""
name = writer.__name__
# Check if the provided writer is known.
if name not in _data_frame_senders.keys():
raise ValueError(
"The provided writer ({}) is not supported, "
"try calling send_string or send_bytes directly.".format(name)
)
# Send data frame using the appropriate send function.
return _data_frame_senders[name](writer, filename, type, **kwargs)


def _send_data_io(data_io, encode, writer, filename, type, **kwargs):
# Some pandas writers try to close the IO, we do not want that.
data_io_close = data_io.close
data_io.close = lambda: None
# Write data content.
writer(data_io, **kwargs)
data_value = data_io.getvalue()
if encode:
data_value = data_value.encode()
data_io_close()
content = base64.b64encode(data_value).decode()
# Wrap in dict.
return dict(content=content, filename=filename, type=type, base64=True)


_data_frame_senders = {
"to_csv": send_string,
"to_json": send_string,
"to_html": send_string,
"to_excel": send_bytes,
"to_feather": send_bytes,
"to_parquet": send_bytes,
"to_msgpack": send_bytes,
"to_stata": send_bytes,
"to_pickle": send_bytes,
}

# endregion
5 changes: 3 additions & 2 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
numpy
pandas
xlrd
pyarrow
mimesis;python_version>="3.6"
virtualenv;python_version=="2.7"
virtualenv;python_version=="2.7"
Loading